Browse Source

Project files

cli_test
Franz Levin 3 months ago
parent
commit
0878293f75
30 changed files with 1912 additions and 0 deletions
  1. +1
    -0
      .gitignore
  2. +155
    -0
      Makefile
  3. +45
    -0
      gcc/drivers.mk
  4. +89
    -0
      gcc/freertos.mk
  5. +27
    -0
      gcc/middleware_usb.mk
  6. +27
    -0
      gcc/middleware_usb_class.mk
  7. +42
    -0
      gcc/project.mk
  8. +26
    -0
      gcc/startup.mk
  9. +31
    -0
      gcc/stm32.mk
  10. +9
    -0
      openocd/flash.mk
  11. +13
    -0
      openocd/openocd.mk
  12. +433
    -0
      project/cli.c
  13. +32
    -0
      project/cli.h
  14. +59
    -0
      project/freertos_adaptations.c
  15. +196
    -0
      project/gpio.c
  16. +6
    -0
      project/gpio.h
  17. +193
    -0
      project/i2c.c
  18. +101
    -0
      project/info.c
  19. +6
    -0
      project/info.h
  20. +43
    -0
      project/main.c
  21. +107
    -0
      project/sensorhub.c
  22. +6
    -0
      project/sensorhub.h
  23. +44
    -0
      project/spi.c
  24. +6
    -0
      project/spi.h
  25. +13
    -0
      project/tasks.h
  26. +23
    -0
      project/usb.c
  27. +7
    -0
      project/usb.h
  28. +141
    -0
      project/usb_uart.c
  29. +15
    -0
      project/usb_uart.h
  30. +16
    -0
      project/utils.h

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
out

+ 155
- 0
Makefile View File

@@ -0,0 +1,155 @@
################################################################################
#
################################################################################

VERBOSE=@

HELP=''

STM_MCU_FAMILY=STM32F0
STM_MCU_SUB_FAMILY=72
STM_MCU_PIN_COUNT=C
STM_MCU_CODE_SIZE=8
STM_MCU_PACKAGE=T
STM_MCU=$(STM_MCU_FAMILY)$(STM_MCU_SUB_FAMILY)$(STM_MCU_PIN_COUNT)$(STM_MCU_CODE_SIZE)

STM_MCU_FAMILY_LOWER=$(shell echo $(STM_MCU_FAMILY) | tr A-Z a-z)
STM_MCU_CODE_SIZE_LOWER=$(shell echo $(STM_MCU_CODE_SIZE) | tr A-Z a-z)

ifeq ($(VARIANT),)
VARIANT = debug
endif

OS := $(shell uname)

ifeq ($(OS),Linux)
TOOLCHAIN := /usr/bin
else
TOOLCHAIN :=
endif
TOOLCHAIN_PREFIX := arm-none-eabi-

CC := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)gcc
GDB := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)gdb
AS := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)as
LD := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)gcc
OBJCOPY := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)objcopy
SIZE := $(TOOLCHAIN)/$(TOOLCHAIN_PREFIX)size

ECHO := echo
MKDIR := mkdir -p
RM := rm -rf

OUT = out/$(VARIANT)
ELF = $(OUT)/stm.elf

CFLAGS += -g

CFLAGS += -mcpu=cortex-m0
CFLAGS += -mthumb
CFLAGS += -mfloat-abi=soft
#CFLAGS += -mfpu=fpv5-sp-d16
CFLAGS += '-D__weak=__attribute__((weak))'
CFLAGS += '-D__packed="__attribute__((__packed__))"'
CFLAGS += -DUSE_HAL_DRIVER
ifeq ($(STM_MCU),STM32F072C8)
CFLAGS += -D$(STM_MCU_FAMILY)$(STM_MCU_SUB_FAMILY)xB
else
CFLAGS += -D$(STM_MCU_FAMILY)$(STM_MCU_SUB_FAMILY)x$(STM_MCU_CODE_SIZE)
endif
CFLAGS += -Wall
CFLAGS += -Werror
CFLAGS += -fmessage-length=0
CFLAGS += -ffunction-sections
CFLAGS += -c
CFLAGS += -fmessage-length=0
#CFLAGS += -MMD
#CFLAGS += -MP

CFLAGS += -Icubemx/Inc
CFLAGS += -Icubemx/Drivers/$(STM_MCU_FAMILY)xx_HAL_Driver/Inc
CFLAGS += -Icubemx/Drivers/$(STM_MCU_FAMILY)xx_HAL_Driver/Inc/Legacy
CFLAGS += -Icubemx/Drivers/CMSIS/Device/ST/$(STM_MCU_FAMILY)xx/Include
CFLAGS += -Icubemx/Drivers/CMSIS/Include
CFLAGS += -Icubemx/Middlewares/Third_Party/FreeRTOS/Source
CFLAGS += -Icubemx/Middlewares/Third_Party/FreeRTOS/Source/include
CFLAGS += -Icubemx/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
CFLAGS += -Icubemx/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM0
CFLAGS += -Icubemx/Middlewares/ST/STM32_USB_Device_Library/Core/Inc
CFLAGS += -Icubemx/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc

ifeq ($(VARIANT),debug)
CFLAGS_PROJECT += -O0
CFLAGS_PROJECT += -DDEBUG_LEVEL=5
else ifeq ($(VARIANT),release)
CFLAGS_PROJECT += -O3
CFLAGS_PROJECT += -DDEBUG_LEVEL=0
CFLAGS_PROJECT += -DNDEBUG
endif
CFLAGS_OPUS += -O3
CFLAGS_OPUS += -DDEBUG_LEVEL=0
CFLAGS_OPUS += -DNDEBUG

LDFLAGS =
LDFLAGS += -mcpu=cortex-m0
LDFLAGS += -mthumb
LDFLAGS += -mfloat-abi=soft
#LDFLAGS += -mfpu=fpv5-sp-d16
LDFLAGS += -specs=nosys.specs
LDFLAGS += -specs=nano.specs
LDFLAGS += -T"cubemx/$(STM_MCU)$(STM_MCU_PACKAGE)x_FLASH.ld"
LDFLAGS += -Wl,-Map=$(OUT)/output.map
LDFLAGS += -Wl,--gc-sections
LDFLAGS += -lm

# All Target
HELP += 'all'
all: $(ELF)

# All of the sources participating in the build are defined here
SOURCE =
include gcc/freertos.mk
include gcc/stm32.mk
include gcc/middleware_usb.mk
include gcc/middleware_usb_class.mk
include gcc/drivers.mk
include gcc/startup.mk
include gcc/project.mk
include openocd/openocd.mk
include openocd/flash.mk

ifneq ($(MAKECMDGOALS),clean)
-include $(addprefix $(OUT)/,$(SOURCE:.c=.d))
endif

OBJC = $(SOURCE:.c=.o)
OBJS = $(subst ../,,$(addprefix $(OUT)/,$(OBJC:.s=.o)))

$(OUT):
$(VERBOSE)$(MKDIR) $@

# Tool invocations
$(ELF): $(OBJS) $(OBJA) cubemx/$(STM_MCU)$(STM_MCU_PACKAGE)x_FLASH.ld | $(OUT)
$(VERBOSE)$(ECHO) '[LD] $@'
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(OBJA) $(LIBS)
$(MAKE) --no-print-directory post-build

# Other Targets
HELP += 'clean'
clean:
-$(VERBOSE)$(ECHO) '[RM] out'
-$(VERBOSE)$(RM) $(OUT)

post-build:
-$(VERBOSE)$(ECHO) 'Generating binary and Printing size information:'
$(VERBOSE)$(OBJCOPY) -O binary $(ELF) $(ELF:.elf=.bin)
$(VERBOSE)$(OBJCOPY) -O binary $(ELF) $(ELF:.elf=.hex)
$(VERBOSE)$(SIZE) $(ELF)
-$(VERBOSE)$(ECHO) ' '

.PHONY: all clean dependents help
.SECONDARY: post-build

help:
-$(VERBOSE)$(ECHO) 'targets: $(HELP)'


+ 45
- 0
gcc/drivers.mk View File

@@ -0,0 +1,45 @@
################################################################################
#
################################################################################

DIR_DRIVERS = cubemx/Drivers/$(STM_MCU_FAMILY)xx_HAL_Driver/Src

# Add inputs and outputs from these tool invocations to the build variables
SOURCE_DRIVERS = \
$(STM_MCU_FAMILY_LOWER)xx_hal.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_cortex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_crc.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_crc_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_dma.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_flash.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_flash_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_gpio.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_i2c.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_i2c_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_pcd_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_pwr.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_pwr_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_rcc.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_rcc_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_spi.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_pcd.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_tim.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_tim_ex.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_uart.c

SOURCE += $(addprefix $(DIR_DRIVERS)/,$(SOURCE_DRIVERS))

# Build .c files
$(OUT)/$(DIR_DRIVERS):
@$(MKDIR) $@

$(OUT)/$(DIR_DRIVERS)/%.o: $(DIR_DRIVERS)/%.c | $(OUT)/$(DIR_DRIVERS)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_DRIVERS)/%.d: $(DIR_DRIVERS)/%.c | $(OUT)/$(DIR_DRIVERS)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 89
- 0
gcc/freertos.mk View File

@@ -0,0 +1,89 @@

################################################################################
#
################################################################################

DIR_FREERTOS = cubemx/Middlewares/Third_Party/FreeRTOS/Source
DIR_CMSISRTOS = $(DIR_FREERTOS)/CMSIS_RTOS
DIR_ARMCM0 = $(DIR_FREERTOS)/portable/GCC/ARM_CM0
DIR_MEMMANG = $(DIR_FREERTOS)/portable/MemMang

# Add inputs and outputs from these tool invocations to the build variables
SOURCE_FREERTOS = \
croutine.c \
event_groups.c \
list.c \
queue.c \
tasks.c \
timers.c

SOURCE_CMSISRTOS = \
cmsis_os.c

SOURCE_ARMCM0 = \
port.c

SOURCE_MEMMANG = \
heap_4.c

SOURCE += $(addprefix $(DIR_ARMCM0)/,$(SOURCE_ARMCM0))
SOURCE += $(addprefix $(DIR_MEMMANG)/,$(SOURCE_MEMMANG))
SOURCE += $(addprefix $(DIR_FREERTOS)/,$(SOURCE_FREERTOS))
SOURCE += $(addprefix $(DIR_CMSISRTOS)/,$(SOURCE_CMSISRTOS))

# Build .c files
$(OUT)/$(DIR_CMSISRTOS):
@$(MKDIR) $@

$(OUT)/$(DIR_CMSISRTOS)/%.o: $(DIR_CMSISRTOS)/%.c | $(OUT)/$(DIR_CMSISRTOS)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_CMSISRTOS)/%.d: $(DIR_CMSISRTOS)/%.c | $(OUT)/$(DIR_CMSISRTOS)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@

# Build .c files
$(OUT)/$(DIR_ARMCM0):
@$(MKDIR) $@

$(OUT)/$(DIR_ARMCM0)/%.o: $(DIR_ARMCM0)/%.c | $(OUT)/$(DIR_ARMCM0)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_ARMCM0)/%.d: $(DIR_ARMCM0)/%.c | $(OUT)/$(DIR_ARMCM0)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@

# Build .c files
$(OUT)/$(DIR_MEMMANG):
@$(MKDIR) $@

$(OUT)/$(DIR_MEMMANG)/%.o: $(DIR_MEMMANG)/%.c | $(OUT)/$(DIR_MEMMANG)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_MEMMANG)/%.d: $(DIR_MEMMANG)/%.c | $(OUT)/$(DIR_MEMMANG)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@

# Build .c files
$(OUT)/$(DIR_FREERTOS):
@$(MKDIR) $@

$(OUT)/$(DIR_FREERTOS)/%.o: $(DIR_FREERTOS)/%.c | $(OUT)/$(DIR_FREERTOS)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_FREERTOS)/%.d: $(DIR_FREERTOS)/%.c | $(OUT)/$(DIR_FREERTOS)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 27
- 0
gcc/middleware_usb.mk View File

@@ -0,0 +1,27 @@
################################################################################
#
################################################################################

DIR_MIDDLEWARE_STM = cubemx/Middlewares/ST/STM32_USB_Device_Library/Core/Src

SOURCE_MIDDLEWARE_STM = \
usbd_core.c \
usbd_ctlreq.c \
usbd_ioreq.c

SOURCE += $(addprefix $(DIR_MIDDLEWARE_STM)/,$(SOURCE_MIDDLEWARE_STM))

# Build .c files
$(OUT)/$(DIR_MIDDLEWARE_STM):
@$(MKDIR) $@

$(OUT)/$(DIR_MIDDLEWARE_STM)/%.o: $(DIR_MIDDLEWARE_STM)/%.c | $(OUT)/$(DIR_MIDDLEWARE_STM)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_MIDDLEWARE_STM) -o "$@" "$<"

$(OUT)/$(DIR_MIDDLEWARE_STM)/%.d: $(DIR_MIDDLEWARE_STM)/%.c | $(OUT)/$(DIR_MIDDLEWARE_STM)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_STM) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 27
- 0
gcc/middleware_usb_class.mk View File

@@ -0,0 +1,27 @@
################################################################################
#
################################################################################

cubemx/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c:

DIR_MIDDLEWARE_USB_CLASS = cubemx/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src

SOURCE_MIDDLEWARE_USB_CLASS = \
usbd_cdc.c

SOURCE += $(addprefix $(DIR_MIDDLEWARE_USB_CLASS)/,$(SOURCE_MIDDLEWARE_USB_CLASS))

# Build .c files
$(OUT)/$(DIR_MIDDLEWARE_USB_CLASS):
@$(MKDIR) $@

$(OUT)/$(DIR_MIDDLEWARE_USB_CLASS)/%.o: $(DIR_MIDDLEWARE_USB_CLASS)/%.c | $(OUT)/$(DIR_MIDDLEWARE_USB_CLASS)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_MIDDLEWARE_USB_CLASS) -o "$@" "$<"

$(OUT)/$(DIR_MIDDLEWARE_USB_CLASS)/%.d: $(DIR_MIDDLEWARE_USB_CLASS)/%.c | $(OUT)/$(DIR_MIDDLEWARE_USB_CLASS)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_USB_CLASS) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 42
- 0
gcc/project.mk View File

@@ -0,0 +1,42 @@
################################################################################
#
################################################################################

DIR_PROJECT = project

SOURCE_PROJECT = \
cli.c \
gpio.c \
spi.c \
i2c.c \
drivers/bmp280.c \
drivers/htu21.c \
sensorhub.c \
info.c \
usb.c \
usb_uart.c \
freertos_adaptations.c \
main.c

CFLAGS += -DTARGET_SMT32F0
CFLAGS += -DICE40_LP384

CFLAGS += -Iproject

SOURCE += $(addprefix $(DIR_PROJECT)/,$(SOURCE_PROJECT))

# Build .c files
$(OUT)/$(DIR_PROJECT):
@$(MKDIR) $@
@$(MKDIR) $@/drivers

$(OUT)/$(DIR_PROJECT)/%.o: $(DIR_PROJECT)/%.c | $(OUT)/$(DIR_PROJECT)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -o "$@" "$<"

$(OUT)/$(DIR_PROJECT)/%.d: $(DIR_PROJECT)/%.c | $(OUT)/$(DIR_PROJECT)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_PROJECT) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 26
- 0
gcc/startup.mk View File

@@ -0,0 +1,26 @@
################################################################################
#
################################################################################

DIR_STARTUP = cubemx

SOURCE_STARTUP =

ifeq ($(STM_MCU),STM32F072C8)
SOURCE_STARTUP += \
startup_$(STM_MCU_FAMILY_LOWER)$(STM_MCU_SUB_FAMILY)xb.s
else
SOURCE_STARTUP += \
startup_$(STM_MCU_FAMILY_LOWER)$(STM_MCU_SUB_FAMILY)x$(STM_MCU_CODE_SIZE_LOWER).s
endif

SOURCE += $(addprefix $(DIR_STARTUP)/,$(SOURCE_STARTUP))

# Build .c files
$(OUT)/$(DIR_STARTUP):
@$(MKDIR) $@

$(OUT)/$(DIR_STARTUP)/%.o: $(DIR_STARTUP)/%.s | $(OUT)/$(DIR_STARTUP)
$(VERBOSE)$(ECHO) '[AS] $<'
$(VERBOSE)$(CC) $(CFLAGS) -o "$@" "$<"


+ 31
- 0
gcc/stm32.mk View File

@@ -0,0 +1,31 @@
################################################################################
#
################################################################################

DIR_STM = cubemx/Src

SOURCE_STM = \
$(STM_MCU_FAMILY_LOWER)xx_hal_msp.c \
$(STM_MCU_FAMILY_LOWER)xx_hal_timebase_TIM.c \
$(STM_MCU_FAMILY_LOWER)xx_it.c \
usbd_conf.c \
usbd_desc.c \
system_$(STM_MCU_FAMILY_LOWER)xx.c \
main.c

SOURCE += $(addprefix $(DIR_STM)/,$(SOURCE_STM))

# Build .c files
$(OUT)/$(DIR_STM):
@$(MKDIR) $@

$(OUT)/$(DIR_STM)/%.o: $(DIR_STM)/%.c | $(OUT)/$(DIR_STM)
$(VERBOSE)$(ECHO) '[CC] $<'
$(VERBOSE)$(CC) $(CFLAGS) $(CFLAGS_STM) -o "$@" "$<"

$(OUT)/$(DIR_STM)/%.d: $(DIR_STM)/%.c | $(OUT)/$(DIR_STM)
@set -e; rm -f $@; \
$(CC) $(CFLAGS) $(CFLAGS_STM) -MM $< > $@.$$$$; \
sed 's,\($<\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$; [ -s $@ ] || rm -f $@


+ 9
- 0
openocd/flash.mk View File

@@ -0,0 +1,9 @@
.PHONY: flash run

HELP += 'flash'
flash: openocd $(ELF)
$(VERBOSE)echo -e "flash banks\nreset halt\nprogram $(ELF) verify\nreset run\nexit\n" | nc localhost $(openocd_telnet_port)

HELP += 'run'
run: flash
$(VERBOSE)$(GDB) $(ELF) -ex "target remote localhost:$(openocd_gdb_port)" -ex "mon reset halt"

+ 13
- 0
openocd/openocd.mk View File

@@ -0,0 +1,13 @@

.PHONY: openocd

openocd_gdb_port = 3333
openocd_tcl_port = 6666
openocd_telnet_port = 4444

HELP += 'openocd'
openocd:
$(VERBOSE)if ! ps axocommand|grep ^openocd > /dev/null; then \
echo [starting openocd]; \
tmux new-session -s openocd -n openocd -d 'openocd -f interface/stlink-v2.cfg -f target/stm32f0x.cfg -c "gdb_port $(openocd_gdb_port)" -c "tcl_port $(openocd_tcl_port)" -c "telnet_port $(openocd_telnet_port)" -c "init;reset halt"'; \
fi

+ 433
- 0
project/cli.c View File

@@ -0,0 +1,433 @@

#include "cli.h"

#include <stdbool.h>
#include <string.h>
#include <ctype.h>

#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>
#include <event_groups.h>

#include "usb_uart.h"
#include "tasks.h"
#include "utils.h"

#define MAX_CLI_LINE 100
#define MAX_ARGS 10

#define FLAG(x) (1<<(x))

#define NEWLINE "\r\n"
#define UNKNOWN_COMMAND "Unknown command: "

typedef enum {
cli_flag_line_ready,
} cli_flag_t;

static struct {
struct {
int current_pos;
uint8_t buffer[MAX_CLI_LINE];
SemaphoreHandle_t semaphore;
EventGroupHandle_t flags;
} line;
struct {
cli_command_t* list;
SemaphoreHandle_t mutex;
} commands;
struct {
TaskHandle_t handle;
StackType_t stack[TASK_STACK_CLI];
StaticTask_t task;
} task;
} cli_data;

static void input(uint8_t* data, int length, void* userdata)
{
int size;
int old_pos;
uint8_t* c;
BaseType_t os_res;
EventBits_t bits;
BaseType_t wake_task = pdFALSE;
BaseType_t wake;

os_res = xSemaphoreTakeFromISR(cli_data.line.semaphore, NULL);
if (os_res != pdTRUE)
{
return;
}

bits = xEventGroupGetBitsFromISR(cli_data.line.flags);
if (bits & FLAG(cli_flag_line_ready))
{
goto out;
}

old_pos = cli_data.line.current_pos;

size = MIN(length, sizeof(cli_data.line.buffer) - cli_data.line.current_pos - 1);

memcpy(&cli_data.line.buffer[cli_data.line.current_pos], data, size);

cli_data.line.current_pos += size;

c = memchr(cli_data.line.buffer, '\r', cli_data.line.current_pos);
if (c == NULL)
{
c = memchr(cli_data.line.buffer, '\n', cli_data.line.current_pos);
}

if (c == NULL)
{
usb_uart_send_data_ISR(data, length);
if (cli_data.line.current_pos >= ARRAYSIZE(cli_data.line.buffer) - 1)
{
if (memchr(data, '\r', length) != NULL ||
memchr(data, '\n', length) != NULL)
{
cli_data.line.current_pos = 0;
}
}
}
else
{
c[0] = '\r';
c[1] = '\n';

usb_uart_send_data_ISR(&cli_data.line.buffer[old_pos], c - &cli_data.line.buffer[old_pos] + 2);

c[0] = '\0';

cli_data.line.current_pos = 0;

wake = pdFALSE;
os_res = xEventGroupSetBitsFromISR(cli_data.line.flags, FLAG(cli_flag_line_ready), &wake);
if (wake == pdTRUE)
{
wake_task = pdTRUE;
}
}

out:
wake = pdFALSE;
os_res = xSemaphoreGiveFromISR(cli_data.line.semaphore, &wake);
if (wake == pdTRUE)
{
wake_task = pdTRUE;
}

if (wake_task)
{
portYIELD_FROM_ISR(wake_task);
}
}

static int send_string(const char* string)
{
return usb_uart_send_data((uint8_t*)string, strlen(string));
}

static int send_char(const unsigned char c)
{
return usb_uart_send_data(&c, 1);
}

static const char* const get_number(uint8_t num)
{
switch (num)
{
case 0: return "0";
case 1: return "1";
case 2: return "2";
case 3: return "3";
case 4: return "4";
case 5: return "5";
case 6: return "6";
case 7: return "7";
case 8: return "8";
case 9: return "9";
default: return "?";
}
}

static int send_int(int32_t value)
{
int32_t i;
uint32_t uvalue;
int print_count = 0;

if (value < 0)
{
send_string("-");
print_count++;
uvalue = -1 * value;
}
else
{
uvalue = value;
}

for (i = 1000000000; i > 0; i /= 10)
{
const char* string;

if (uvalue/i != 0)
{
string = get_number(uvalue/i);
send_string(string);
print_count++;
}

uvalue %= i;
}

if (print_count == 0)
{
send_string("0");
print_count++;
}

return print_count;
}

static int send_uint(uint32_t value)
{
uint32_t i;
int print_count = 0;

for (i = 1000000000; i > 0; i /= 10)
{
const char* string;

if (value/i != 0)
{
string = get_number(value/i);
send_string(string);
print_count++;
}

value %= i;
}

if (print_count == 0)
{
send_string("0");
print_count++;
}

return print_count;
}

int send_hex(uint32_t value)
{
int i;
int print_count = 0;

send_string("0x");
print_count += 2;

i = sizeof(value) * 2;

do
{
i--;
send_char("0123456789abcdef"[(value >> (i*4)) & 0xf]);
print_count++;
} while (i > 0);

return print_count;
}

static void cli_task(void* data)
{
while (true)
{
BaseType_t os_res;
EventBits_t bits;

bits = xEventGroupWaitBits(cli_data.line.flags, FLAG(cli_flag_line_ready), pdFALSE, pdFALSE, portMAX_DELAY);
os_res = xSemaphoreTake(cli_data.line.semaphore, portMAX_DELAY);

if (os_res != pdTRUE)
{
continue;
}

if (bits & FLAG(cli_flag_line_ready))
{
char* c;
int argc;
char* argv[MAX_ARGS];
cli_command_t* command;
bool command_found = false;;
cli_print_t print = {
.print = usb_uart_send_data,
.printline = send_string,
.printint = send_int,
.printuint = send_uint,
.printhex = send_hex,
.newline = NEWLINE,
};

c = (char*)cli_data.line.buffer;

while (isspace((int)*c))
{
c++;
}

// Command
argv[0] = c;
argc = 1;

// Arguments
while ((c = strchr(c, ' ')) != NULL)
{
*c = '\0';
c++;
if (!isspace((int)*c) &&
*c != '\0' &&
argc < ARRAYSIZE(argv) - 1)
{
argv[argc] = c;
argc++;
}
}

command = cli_data.commands.list;
while (command != NULL)
{
if (strcmp(argv[0], command->name) == 0)
{
command->function(argc, argv, &print);
command_found = true;
}
command = command->next;
}

if (!command_found)
{
print.printline(UNKNOWN_COMMAND);
print.printline(argv[0]);
print.printline(NEWLINE);
}
}

xEventGroupClearBits(cli_data.line.flags, FLAG(cli_flag_line_ready));
xSemaphoreGive(cli_data.line.semaphore);
}
}

static int cli_command_help(int argc, char* const argv[], cli_print_t* print)
{
BaseType_t os_res;
cli_command_t* current;
char spaces[24];

os_res = xSemaphoreTake(cli_data.commands.mutex, portMAX_DELAY);
if (os_res != pdTRUE)
{
return 1;
}

memset(spaces, ' ', sizeof(spaces));

current = cli_data.commands.list;
while (current != NULL)
{
print->printline(current->name);
print->print((uint8_t*)spaces, sizeof(spaces) - strlen(current->name));
print->printline(current->help);
print->printline(print->newline);
current = current->next;
}

xSemaphoreGive(cli_data.commands.mutex);
return 0;
}

static int cli_command_echo(int argc, char* const argv[], cli_print_t* print)
{
int i;

for (i = 1; i < argc; i++)
{
print->printline(argv[i]);
print->printline(" ");
}
print->printline(print->newline);

return 0;
}

int cli_register_command(cli_command_t* command)
{
BaseType_t os_res;
cli_command_t* current;

if (command == NULL)
{
return 1;
}

command->next = NULL;

os_res = xSemaphoreTake(cli_data.commands.mutex, portMAX_DELAY);
if (os_res != pdTRUE)
{
return 1;
}

if (cli_data.commands.list == NULL)
{
cli_data.commands.list = command;
}
else
{
current = cli_data.commands.list;

while (current->next != NULL)
{
current = current->next;
}

current->next = command;
}

xSemaphoreGive(cli_data.commands.mutex);
return 0;
}

int cli_init(void)
{
static cli_command_t command_help = {
.name = "help",
.help = "list available commands",
.function = cli_command_help,
};

static cli_command_t command_echo = {
.name = "echo",
.help = "echo all arguments",
.function = cli_command_echo,
};

cli_data.line.semaphore = xSemaphoreCreateBinary();
xSemaphoreGive(cli_data.line.semaphore);

cli_data.line.flags = xEventGroupCreate();

cli_data.commands.mutex = xSemaphoreCreateMutex();

cli_data.task.handle = xTaskCreateStatic(cli_task, TASK_NAME_CLI, ARRAYSIZE(cli_data.task.stack)/4, NULL, TASK_PRIO_CLI, cli_data.task.stack, &cli_data.task.task);

usb_uart_register_receiver(input, NULL);

cli_register_command(&command_help);
cli_register_command(&command_echo);

return 0;
}

+ 32
- 0
project/cli.h View File

@@ -0,0 +1,32 @@
#ifndef CLI_H
#define CLI_H

#include <stdint.h>

typedef struct {
int (*print)(const uint8_t* data, int length);
int (*printline)(const char* string);
int (*printint)(int32_t value);
int (*printuint)(uint32_t value);
int (*printhex)(uint32_t value);
const char* newline;
} cli_print_t;

typedef int (*cli_function_t)(int argc, char* const argv[], cli_print_t* print);

typedef struct cli_command_t cli_command_t;
struct cli_command_t {
const char* name;
const char* help;
cli_function_t function;
cli_command_t* next;
};

/*
* Note: command must be allocated and kept allocated by the caller.
*/
int cli_register_command(cli_command_t* command);

int cli_init(void);

#endif // CLI_H

+ 59
- 0
project/freertos_adaptations.c View File

@@ -0,0 +1,59 @@
// Example from https://www.freertos.org/a00110.html

#include <stdint.h>

#include <FreeRTOS.h>
#include <task.h>

/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];

/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;

/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;

/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/

/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];

/* Pass out a pointer to the StaticTask_t structure in which the Timer
task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;

/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;

/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

+ 196
- 0
project/gpio.c View File

@@ -0,0 +1,196 @@
#include "gpio.h"

#include <stdlib.h>
#include <string.h>

#include <stm32f0xx_hal.h>

#include "cli.h"

static int start_clock(char c)
{
switch (c)
{
case 'A': __HAL_RCC_GPIOA_CLK_ENABLE(); return 0;
case 'B': __HAL_RCC_GPIOB_CLK_ENABLE(); return 0;
case 'C': __HAL_RCC_GPIOC_CLK_ENABLE(); return 0;
case 'D': __HAL_RCC_GPIOD_CLK_ENABLE(); return 0;
case 'F': __HAL_RCC_GPIOF_CLK_ENABLE(); return 0;
default: return 1;
}
}

static int get_gpio_base(char c, GPIO_TypeDef** gpio_base)
{
switch (c)
{
case 'A': *gpio_base = GPIOA; return 0;
case 'B': *gpio_base = GPIOB; return 0;
case 'C': *gpio_base = GPIOC; return 0;
case 'D': *gpio_base = GPIOD; return 0;
case 'F': *gpio_base = GPIOF; return 0;
default: return 1;
}
}
static int get_pin(const char* string, uint32_t* pin)
{
int pin_number;

pin_number = strtol(string, NULL, 0);

switch (pin_number)
{
case 0: *pin = GPIO_PIN_0; return 0;
case 1: *pin = GPIO_PIN_1; return 0;
case 2: *pin = GPIO_PIN_2; return 0;
case 3: *pin = GPIO_PIN_3; return 0;
case 4: *pin = GPIO_PIN_4; return 0;
case 5: *pin = GPIO_PIN_5; return 0;
case 6: *pin = GPIO_PIN_6; return 0;
case 7: *pin = GPIO_PIN_7; return 0;
case 8: *pin = GPIO_PIN_8; return 0;
case 9: *pin = GPIO_PIN_9; return 0;
case 10: *pin = GPIO_PIN_10; return 0;
case 11: *pin = GPIO_PIN_11; return 0;
case 12: *pin = GPIO_PIN_12; return 0;
case 13: *pin = GPIO_PIN_13; return 0;
case 14: *pin = GPIO_PIN_14; return 0;
case 15: *pin = GPIO_PIN_15; return 0;
default: return 1;
}
}

static int gpio_command(int argc, char* const argv[], cli_print_t* print)
{
GPIO_InitTypeDef gpio_setting;

if (argc < 2)
{
print->printline("Too few arguments: ");
print->printline(argv[0]);
print->printline(" get|set pin [value]");
print->printline(print->newline);
return 1;
}
else if (argc == 3 && strcmp(argv[1], "get") == 0)
{
GPIO_TypeDef* gpio_base;
const char* pin = argv[2];

if (get_gpio_base(*pin, &gpio_base) != 0)
{
print->printline("unsupported gpio base: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

if (start_clock(*pin) != 0)
{
print->printline("unsupported gpio base: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

if (get_pin(&pin[1], &gpio_setting.Pin) != 0)
{
print->printline("unsupported pin number: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

gpio_setting.Mode = GPIO_MODE_INPUT;
gpio_setting.Pull = GPIO_NOPULL;
gpio_setting.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_setting.Alternate = 0;

HAL_GPIO_Init(gpio_base, &gpio_setting);

print->printline(pin);
print->printline(": ");
switch (HAL_GPIO_ReadPin(gpio_base, gpio_setting.Pin))
{
case GPIO_PIN_RESET:
print->printline("0");
break;
case GPIO_PIN_SET:
print->printline("1");
break;
}

print->printline(print->newline);
}
else if (argc == 4 && strcmp(argv[1], "set") == 0)
{
GPIO_TypeDef* gpio_base;
const char* pin = argv[2];
const char* value = argv[3];

if (get_gpio_base(*pin, &gpio_base) != 0)
{
print->printline("unsupported gpio base: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

if (start_clock(*pin) != 0)
{
print->printline("unsupported gpio base: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

if (get_pin(&pin[1], &gpio_setting.Pin) != 0)
{
print->printline("unsupported pin number: ");
print->printline(pin);
print->printline(print->newline);
return 1;
}

gpio_setting.Mode = GPIO_MODE_OUTPUT_PP;
gpio_setting.Pull = GPIO_NOPULL;
gpio_setting.Speed = GPIO_SPEED_FREQ_HIGH;
gpio_setting.Alternate = 0;

HAL_GPIO_Init(gpio_base, &gpio_setting);

if (strcmp(value, "0") == 0)
{
HAL_GPIO_WritePin(gpio_base, gpio_setting.Pin, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(gpio_base, gpio_setting.Pin, GPIO_PIN_SET);
}
}
else
{
print->printline("Unknown gpio command or wrong number of arguments: ");
print->printline(argv[1]);
print->printline(print->newline);
return 1;
}

return 0;
}

int gpio_init(void)
{

static cli_command_t command_gpio = {
.name = "gpio",
.help = "set/get gpio state",
.function = gpio_command,
};

cli_register_command(&command_gpio);

return 0;
}


+ 6
- 0
project/gpio.h View File

@@ -0,0 +1,6 @@
#ifndef GPIO_H
#define GPIO_H

int gpio_init(void);

#endif // GPIO_H

+ 193
- 0
project/i2c.c View File

@@ -0,0 +1,193 @@
#include "drivers/drivers.h"
#include "drivers/i2c.h"

#include <stdint.h>
#include <string.h>
#include <stm32f0xx_hal.h>

#include "cli.h"

#define I2C_TIMEOUT 100 // ms

static struct {
I2C_HandleTypeDef handler;
} i2c;

static bool i2c_print(driver_bus_params_t* params, driver_print_data_t* data)
{
return true;
}

static int i2c_setup(int port, int pin_map)
{
HAL_StatusTypeDef hal_status;
GPIO_InitTypeDef gpio;

switch (port)
{
case 1: i2c.handler.Instance = I2C1; break;
case 2: i2c.handler.Instance = I2C2; break;
default: return 1;
}

switch (pin_map)
{
case 1: gpio.Pin = GPIO_PIN_6|GPIO_PIN_7; break;
case 2: gpio.Pin = GPIO_PIN_8|GPIO_PIN_9; break;
default: return 1;
}

__HAL_RCC_GPIOB_CLK_ENABLE();

gpio.Mode = GPIO_MODE_AF_OD;
gpio.Pull = GPIO_NOPULL;
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
gpio.Alternate = GPIO_AF1_I2C1;

HAL_GPIO_Init(GPIOB, &gpio);

switch (port)
{
case 1: __HAL_RCC_I2C1_CLK_ENABLE(); break;
case 2: __HAL_RCC_I2C2_CLK_ENABLE(); break;
}

i2c.handler.Init.Timing = 0x2000090E;
i2c.handler.Init.OwnAddress1 = 0;
i2c.handler.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
i2c.handler.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
i2c.handler.Init.OwnAddress2 = 0;
i2c.handler.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
i2c.handler.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
i2c.handler.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

hal_status = HAL_I2C_Init(&i2c.handler);
if (hal_status != HAL_OK)
{
return 1;
}

hal_status = HAL_I2CEx_ConfigAnalogFilter(&i2c.handler, I2C_ANALOGFILTER_ENABLE);
if (hal_status != HAL_OK)
{
return 1;
}

hal_status = HAL_I2CEx_ConfigDigitalFilter(&i2c.handler, 0);
if (hal_status != HAL_OK)
{
return 1;
}

return 0;
}

static int i2c_command(int argc, char* const argv[], cli_print_t* print)
{

if (argc < 2)
{
print->printline("Too few arguments: ");
print->printline(argv[0]);
print->printline(" enable|disable|scan");
print->printline(print->newline);
}
else if (strcmp(argv[1], "enable") == 0)
{
print->printline("Already enabled\n");
print->printline(print->newline);
}
else if (strcmp(argv[1], "disable") == 0)
{
print->printline("Not implemented\n");
print->printline(print->newline);
}
else if (strcmp(argv[1], "scan") == 0)
{
HAL_StatusTypeDef hal_status;
uint8_t address;
uint8_t data[1] = {0};

for (address = 1; address < 0x7F; address++)
{
hal_status = HAL_I2C_Master_Transmit(&i2c.handler, address<<1, data, 0, 10);
if (hal_status == HAL_OK)
{
print->printint(address);
print->printline(" 0x");
print->printhex(address);
print->printline(print->newline);
}
}
print->printline("Scan done");
print->printline(print->newline);
}
else
{
print->printline("Unknown i2c command or wrong number of arguments");
print->printline(argv[1]);
print->printline(print->newline);
return 1;
}

return 0;
}

int i2c_transmit(i2c_t* i2c_, uint8_t address, uint8_t* data, uint8_t length)
{
HAL_StatusTypeDef hal_status;

hal_status = HAL_I2C_Master_Transmit(&i2c.handler, address<<1, data, length, I2C_TIMEOUT);
if (hal_status != HAL_OK)
{
return 1;
}

return 0;
}

int i2c_transmit_no_stop(i2c_t* i2c_, uint8_t address, uint8_t* data, uint8_t length)
{
HAL_StatusTypeDef hal_status;

hal_status = HAL_I2C_Master_Transmit_2(&i2c.handler, address<<1, data, length, I2C_TIMEOUT, true);
if (hal_status != HAL_OK)
{
return 1;
}

return 0;
}

int i2c_receive(i2c_t* i2c_, uint8_t address, uint8_t* data, uint8_t length)
{
HAL_StatusTypeDef hal_status;

hal_status = HAL_I2C_Master_Receive(&i2c.handler, address<<1, data, length, I2C_TIMEOUT);
if (hal_status != HAL_OK)
{
return 1;
}

return 0;
}

static bool i2c_init(driver_bus_params_t* params)
{
static cli_command_t command_i2c = {
.name = "i2c",
.help = "enable/disable i2c",
.function = i2c_command,
};

cli_register_command(&command_i2c);

i2c_setup(1, 2);

return true;
}

const driver_bus_type_t bus_i2c = {
.init = i2c_init,
.print = i2c_print,
};

+ 101
- 0
project/info.c View File

@@ -0,0 +1,101 @@

#include "info.h"

#include <string.h>

#include <FreeRTOS.h>
#include <task.h>

#include "cli.h"

#define PRINT_TASK_NAME_LENGTH 12
#define PRINT_TASK_STATE_LENGTH 12
#define PRINT_TASK_PRIO_LENGTH 6

static int info_command_tasks(int argc, char* const argv[], cli_print_t* print)
{
{
int i;
int print_count;
int task_count;
TaskStatus_t* task_status;
uint8_t spaces[24];

memset(spaces, ' ', sizeof(spaces));

task_count = uxTaskGetNumberOfTasks();

task_status = pvPortMalloc(task_count * sizeof(*task_status));

if (task_status != NULL)
{
task_count = uxTaskGetSystemState(task_status, task_count, NULL);

print_count = print->printline("name");
print->print(spaces, PRINT_TASK_NAME_LENGTH - print_count);

print_count = print->printline("state");
print->print(spaces, PRINT_TASK_STATE_LENGTH - print_count);

print_count = print->printline("prio");

print->printline(print->newline);

for (i = 0; i < task_count; i++)
{
const char* string;

print_count = print->printline(task_status[i].pcTaskName);
print->print(spaces, PRINT_TASK_NAME_LENGTH - print_count);

switch (task_status[i].eCurrentState)
{
case eRunning: string = "running"; break;
case eReady: string = "ready"; break;
case eBlocked: string = "blocked"; break;
case eSuspended: string = "suspended"; break;
case eDeleted: string = "deleted"; break;
case eInvalid: string = "invalid"; break;
default: string = "unknown"; break;
}
print_count = print->printline(string);
print->print(spaces, PRINT_TASK_STATE_LENGTH - print_count);

print_count += print->printuint(task_status[i].uxCurrentPriority);
print_count += print->printline("(");
print_count += print->printuint(task_status[i].uxBasePriority);
print_count += print->printline(")");

print->printline(print->newline);
}
}
vPortFree(task_status);
}

{
size_t heap;

print->printline("Free heap: ");

heap = xPortGetFreeHeapSize();

print->printuint(heap);
print->printline(print->newline);
}

return 0;
}

int info_init(void)
{
static cli_command_t command_tasks = {
.name = "tasks",
.help = "print tasks",
.function = info_command_tasks,
};

cli_register_command(&command_tasks);

return 0;
}


+ 6
- 0
project/info.h View File

@@ -0,0 +1,6 @@
#ifndef INFO_H
#define INFO_H

int info_init(void);

#endif // INFO_H

+ 43
- 0
project/main.c View File

@@ -0,0 +1,43 @@
#include <stm32f0xx_hal.h>

#include <FreeRTOS.h>
#include <task.h>

#include "usb.h"
#include "gpio.h"
#include "spi.h"
#include "drivers/i2c.h"
#include "cli.h"
#include "info.h"

#include "sensorhub.h"

// From cubemx main.c
void SystemClock_Config(void);

int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* Configure the system clock */
SystemClock_Config();

usb_init();

cli_init();
info_init();
gpio_init();

sensorhub_init();

/* Start scheduler */
vTaskStartScheduler();

/* We should never get here as control is now taken by the scheduler */

/* Infinite loop */
while (1)
{
}
}

+ 107
- 0
project/sensorhub.c View File

@@ -0,0 +1,107 @@

#include "sensorhub.h"

#include <stdbool.h>

#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>

#include "usb_uart.h"
#include "tasks.h"
#include "utils.h"

#include "drivers/drivers.h"

#include <stm32f0xx_hal.h>

int send_hex(uint32_t value);

static driver_bus_t driver_buses[] = {
{ .bus = &bus_i2c },
};

static driver_t driver_sensors[] = {
#if 1
{ .bus = &driver_buses[0], .sensor = &sensor_bmp280,
.params.bmp280.sdo_high = false,
.params.bmp280.temp_oversampling = 1,
.params.bmp280.pressure_oversampling = 2, },
#endif
#if 1
{ .bus = &driver_buses[0], .sensor = &sensor_htu21, },
#endif
};

static struct {
struct {
TaskHandle_t handle;
StackType_t stack[TASK_STACK_SENSORHUB];
StaticTask_t task;
} task;
} sensorhub_data;

static bool print_value(char* data, uint16_t* index, int i, const char* string, void* value, int size)
{
usb_uart_send_data((unsigned char*)string, strlen(string));
usb_uart_send_data((unsigned char*)": ", 2);
switch (size)
{
case 1: send_hex(*(uint8_t*)value); break;
case 2: send_hex(*(uint16_t*)value); break;
case 4: send_hex(*(uint32_t*)value); break;
default: break;
}
usb_uart_send_data((unsigned char*)"\r\n", 2);
return true;
}

static bool print_string(char* data, uint16_t* index, int i, const char* string, const char* value)
{
usb_uart_send_data((unsigned char*)string, strlen(string));
usb_uart_send_data((unsigned char*)": ", 2);
usb_uart_send_data((unsigned char*)value, strlen(value));
usb_uart_send_data((unsigned char*)"\r\n", 2);
return true;
}

static void sensorhub_task(void* data)
{
int i;

driver_print_data_t print_data = {
.data = NULL,
.index = 0,
.print_value = print_value,
.print_string = print_string,
};

for (i = 0; i < ARRAYSIZE(driver_buses); i++)
{
driver_buses[i].bus->init(&driver_buses[i].params);
}

for (i = 0; i < ARRAYSIZE(driver_sensors); i++)
{
driver_sensors[i].sensor->init(&driver_sensors[i].params, driver_sensors[i].bus);
}

while (true)
{
vTaskDelay(2000 / portTICK_PERIOD_MS);
usb_uart_send_data((unsigned char*)"sensorhub\r\n", 11);
for (i = 0; i < ARRAYSIZE(driver_sensors); i++)
{
driver_sensors[i].sensor->read(&driver_sensors[i].params);
driver_sensors[i].sensor->print(&driver_sensors[i].params, &print_data);
}

}
}

int sensorhub_init(void)
{
sensorhub_data.task.handle = xTaskCreateStatic(sensorhub_task, TASK_NAME_SENSORHUB, ARRAYSIZE(sensorhub_data.task.stack)/4, NULL, TASK_PRIO_SENSORHUB, sensorhub_data.task.stack, &sensorhub_data.task.task);

return 0;
}

+ 6
- 0
project/sensorhub.h View File

@@ -0,0 +1,6 @@
#ifndef SENSORHUB_H
#define SENSORHUB_H

int sensorhub_init(void);

#endif // SENSORHUB_H

+ 44
- 0
project/spi.c View File

@@ -0,0 +1,44 @@
#include "spi.h"

#include <string.h>

#include "cli.h"

static int spi_command(int argc, char* const argv[], cli_print_t* print)
{
if (argc < 2)
{
print->printline("Too few arguments: ");
print->printline(argv[0]);
print->printline(" enable|disable");
print->printline(print->newline);
}
else if (strcmp(argv[1], "enable") == 0)
{
}
else if (strcmp(argv[1], "disable") == 0)
{
}
else
{
print->printline("Unknown spi command or wrong number of arguments");
print->printline(argv[1]);
print->printline(print->newline);
return 1;
}

return 0;
}

int spi_init(void)
{
static cli_command_t command_spi = {
.name = "spi",
.help = "enable/disable spi",
.function = spi_command,
};

cli_register_command(&command_spi);

return 0;
}

+ 6
- 0
project/spi.h View File

@@ -0,0 +1,6 @@
#ifndef SPI_H
#define SPI_H

int spi_init(void);

#endif // SPI_H

+ 13
- 0
project/tasks.h View File

@@ -0,0 +1,13 @@
#ifndef TASKS_H
#define TASKS_H

#define TASK_NAME_CLI "cli"
#define TASK_NAME_SENSORHUB "sensorhub"

#define TASK_STACK_CLI 512
#define TASK_STACK_SENSORHUB 512

#define TASK_PRIO_CLI tskIDLE_PRIORITY
#define TASK_PRIO_SENSORHUB tskIDLE_PRIORITY

#endif // TASKS_H

+ 23
- 0
project/usb.c View File

@@ -0,0 +1,23 @@

#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_cdc.h"

#include "usb_uart.h"

static struct {
USBD_HandleTypeDef handle;
} usb_data;

void usb_init(void)
{
USBD_Init(&usb_data.handle, &FS_Desc, DEVICE_FS);

USBD_RegisterClass(&usb_data.handle, &USBD_CDC);

usb_uart_init(&usb_data.handle);

USBD_Start(&usb_data.handle);
}



+ 7
- 0
project/usb.h View File

@@ -0,0 +1,7 @@
#ifndef USB_H
#define USB_H

void usb_init(void);

#endif // USB_H


+ 141
- 0
project/usb_uart.c View File

@@ -0,0 +1,141 @@
#include "usb_uart.h"

#include <stdbool.h>

#include <FreeRTOS.h>
#include <task.h>

#include "usbd_core.h"
#include "usbd_cdc.h"

#include "utils.h"

#define UART_RX_BUFFER_SIZE 100
#define UART_TX_BUFFER_SIZE 100

typedef struct {
usb_uart_receive receive;
void* userdata;
} uart_recevier_t;

static struct {
TaskHandle_t task;
USBD_HandleTypeDef* handle;
uint8_t rx_buffer[UART_RX_BUFFER_SIZE];
uint8_t tx_buffer[UART_TX_BUFFER_SIZE];
uart_recevier_t receivers[1];
} uart_data;

static int8_t cdc_init(void)
{
USBD_CDC_SetTxBuffer(uart_data.handle, uart_data.tx_buffer, 0);
USBD_CDC_SetRxBuffer(uart_data.handle, uart_data.rx_buffer);

return USBD_OK;
}

static int8_t cdc_deinit(void)
{
return USBD_OK;
}

static int8_t cdc_control(uint8_t command, uint8_t* buffer, uint16_t length)
{
switch (command)
{
case CDC_SEND_ENCAPSULATED_COMMAND:
case CDC_GET_ENCAPSULATED_RESPONSE:
case CDC_SET_COMM_FEATURE:
case CDC_GET_COMM_FEATURE:
case CDC_CLEAR_COMM_FEATURE:
case CDC_SET_LINE_CODING:
case CDC_GET_LINE_CODING:
case CDC_SET_CONTROL_LINE_STATE:
case CDC_SEND_BREAK:
default:
break;
}

return USBD_OK;
}

static int8_t cdc_receive(uint8_t* buffer, uint32_t* length)
{
int i;

USBD_CDC_ReceivePacket(uart_data.handle);

for (i = 0; i < ARRAYSIZE(uart_data.receivers); i++)
{
uart_recevier_t* receiver;

receiver = &uart_data.receivers[i];
if (receiver->receive != NULL)
{
receiver->receive(buffer, *length, receiver->userdata);
}
}

return USBD_OK;
}

int usb_uart_register_receiver(usb_uart_receive receive, void* userdata)
{
uart_data.receivers[0].receive = receive;
uart_data.receivers[0].userdata = userdata;

return 0;
}

int usb_uart_send_data_ISR(const uint8_t* data, int length)
{
int written;

written = MIN(length, sizeof(uart_data.tx_buffer));

memcpy(uart_data.tx_buffer, data, written);

USBD_CDC_SetTxBuffer(uart_data.handle, uart_data.tx_buffer, written);
USBD_CDC_TransmitPacket(uart_data.handle);

return written;
}

int usb_uart_send_data(const uint8_t* data, int length)
{
int written;
USBD_CDC_HandleTypeDef* cdc_handle;

written = MIN(length, sizeof(uart_data.tx_buffer));

cdc_handle = (USBD_CDC_HandleTypeDef*)uart_data.handle->pClassData;

while (cdc_handle->TxState != 0)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
}

memcpy(uart_data.tx_buffer, data, written);

USBD_CDC_SetTxBuffer(uart_data.handle, uart_data.tx_buffer, written);
USBD_CDC_TransmitPacket(uart_data.handle);

return written;
}

int usb_uart_init(USBD_HandleTypeDef* handle)
{
static USBD_CDC_ItfTypeDef interface = {
cdc_init,
cdc_deinit,
cdc_control,
cdc_receive,
};

uart_data.handle = handle;

USBD_CDC_RegisterInterface(uart_data.handle, &interface);

return 0;
}


+ 15
- 0
project/usb_uart.h View File

@@ -0,0 +1,15 @@
#ifndef UART_TASK_H
#define uart_TASK_H

#include "usbd_core.h"

typedef void (*usb_uart_receive)(uint8_t* data, int length, void* userdata);

int usb_uart_register_receiver(usb_uart_receive receiver, void* userdata);

int usb_uart_send_data_ISR(const uint8_t* data, int length);
int usb_uart_send_data(const uint8_t* data, int length);

int usb_uart_init(USBD_HandleTypeDef* handle);

#endif // UART_TASK_H

+ 16
- 0
project/utils.h View File

@@ -0,0 +1,16 @@
#ifndef UTILS_H
#define UTILS_H

#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif // MIN

#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif // MAX

#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
#endif // ARRAYSIZE

#endif // UTILS_H

Loading…
Cancel
Save