diff --git a/.cproject b/.cproject index 91234d7..4507fd4 100755 --- a/.cproject +++ b/.cproject @@ -136,7 +136,6 @@ make - all true true @@ -144,7 +143,6 @@ make - clean true true @@ -152,6 +150,7 @@ make + distclean true false @@ -197,9 +196,16 @@ false true + + make + TEST_APP=shell + test + true + false + true + make - all true true @@ -231,7 +237,6 @@ make - distclean true false @@ -261,6 +266,22 @@ false true + + make + TEST_APP=shell BOARD=stm32f4-discovery DEBUG=y + test + true + false + true + + + make + TEST_APP=shell BOARD=stm32f4-discovery DEBUG=y + install + true + false + true + make APP=example_radio_rx BOARD=msp430-ccrf DEBUG=y @@ -287,7 +308,6 @@ make - all true true @@ -295,7 +315,6 @@ make - clean true true diff --git a/Makefile b/Makefile index d874baa..1fccb67 100755 --- a/Makefile +++ b/Makefile @@ -12,6 +12,11 @@ endif MAINFILE = $(EXE_DIR)/lib$(OS_NAME)-$(ARCH)-$(BOARD)$(VERSION)$(DBG_EXT)$(LIB_EXT) DEPLOY_PACKET = lib$(OS_NAME)-$(ARCH)-$(BOARD)$(VERSION)$(DBG_EXT).tar.xz +TEST_FILE = $(EXE_DIR)/$(TEST_APP)$(ELF_EXT) +BIN_FILE = $(EXE_DIR)/$(TEST_APP)$(BIN_EXT) +HEX_FILE = $(EXE_DIR)/$(TEST_APP)$(HEX_EXT) +SIZE_FILE = $(SIZE_DIR)/$(TEST_APP)$(SIZE_EXT) + INCLUDES += $(SRC_DIR) SUB_FOLDER := @@ -25,6 +30,10 @@ DEPS = $(SOURCES:$(ROOT_DIR)/%.c=$(OBJ_DIR)/%.d) #include subfolders include source/firmware/firmware.mk +ifdef TEST_APP +include source/test/test.mk +CFLAGS += -DTEST_APP +endif SOURCES += $(foreach folder, $(SUB_FOLDER), $(wildcard $(ROOT_DIR)/$(folder)/*.c)) CHECKSOURCES += $(foreach folder, $(CHECK_FOLDER), $(wildcard $(ROOT_DIR)/$(folder)/*.c)) @@ -74,6 +83,22 @@ doc: @$(MKDIR) $(DOC_DIR) (cat $(DOXYFILE) ; echo "INPUT=$(DOC_SRC)" ; echo "OUTPUT_DIRECTORY=$(DOC_DIR)") | doxygen - +test: check $(OBJECTS) $(ASM_OBJECTS) + @$(MKDIR) $(EXE_DIR) + @$(MKDIR) $(MAP_DIR) + @$(MKDIR) $(SIZE_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(ASM_OBJECTS) -o $(TEST_FILE) + $(OBJCOPY) $(TEST_FILE) -O binary $(BIN_FILE) + $(OBJCOPY) $(TEST_FILE) -O ihex $(HEX_FILE) + $(NM) --size-sort --print-size $(TEST_FILE) > $(SIZE_FILE) + @echo + @$(SIZE) --format=berkeley -x $(TEST_FILE) + @echo + +install: test + $(PRE_PROGRAM) + $(PROGRAM) + ifneq "$(MAKECMDGOALS)" "clean" -include $(DEPS) else diff --git a/config/linker/stm32_flash.ld b/config/linker/stm32_flash.ld new file mode 100755 index 0000000..7cfdc96 --- /dev/null +++ b/config/linker/stm32_flash.ld @@ -0,0 +1,170 @@ +/* +***************************************************************************** +** +** File : stm32_flash.ld +** +** Abstract : Linker script for STM32F407VG Device with +** 1024KByte FLASH, 192KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of 128K RAM on AHB bus*/ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/config/make/rules.mk b/config/make/rules.mk index 582a77a..5e9a8ec 100755 --- a/config/make/rules.mk +++ b/config/make/rules.mk @@ -1,14 +1,14 @@ -.PHONY: clean distclean doc +.PHONY: clean distclean doc test ROOT_DIR := $(shell pwd | sed "s/\/source//g") -ifeq ($(BOARD), msp430-ccrf) -include $(ROOT_DIR)/config/make/msp430.mk -endif ifeq ($(BOARD), stm32f4-discovery) include $(ROOT_DIR)/config/make/stm32f4xx.mk endif +OS_LIB = kosmos-$(ARCH)-$(BOARD)$(DBG_EXT) +LIBS += $(OS_LIB) + CFLAGS += \ -Wno-unused-function \ -O$(OPTIM) \ diff --git a/config/make/stm32f4xx.mk b/config/make/stm32f4xx.mk index 563d1b2..4a9e9f3 100644 --- a/config/make/stm32f4xx.mk +++ b/config/make/stm32f4xx.mk @@ -23,7 +23,7 @@ endif CFLAGS += \ -mthumb \ - -T $(ROOT_DIR)/source/firmware/arch/stm32f4xx/linker/stm32_flash.ld \ + -T $(ROOT_DIR)/config/linker/stm32_flash.ld \ -D USE_STDPERIPH_DRIVER\ -D VECT_TAB_FLASH\ -D GCC_ARMCM4\ @@ -54,7 +54,7 @@ LDFLAGS=\ ASFLAGS=-mapcs-32 -g ARFLAGS=rcs -OOCD_IMAGE=$(BINFILE) +OOCD_IMAGE=$(BIN_FILE) OOCD_CFG_FILE=$(EXE_DIR)/openocd.cfg PRE_PROGRAM = echo "telnet_port 4444\ninit\nreset halt\nflash write_image erase $(OOCD_IMAGE) 0x08000000 bin\nreset run\n shutdown\n" > $(OOCD_CFG_FILE) diff --git a/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h b/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h index d393075..81faad3 100755 --- a/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h +++ b/source/firmware/arch/stm32f4xx/board/stm32f4-discovery/include/stm32f4-discovery.h @@ -86,7 +86,11 @@ static const struct uart __uart_1 = { &console_buffer, }; +#ifdef TEST_APP +static const struct driver uart_1 = { +#else const struct driver uart_1 = { +#endif DRIVER_TYPE_UART, &__uart_1, }; @@ -114,7 +118,11 @@ static const struct gpio __led_3 = { &gpio_fp }; +#ifdef TEST_APP +static const struct driver led_3 = { +#else const struct driver led_3 = { +#endif DRIVER_TYPE_GPIO, &__led_3, }; @@ -142,7 +150,11 @@ static const struct gpio __led_4 = { &gpio_fp }; +#ifdef TEST_APP +static const struct driver led_4 = { +#else const struct driver led_4 = { +#endif DRIVER_TYPE_GPIO, &__led_4, }; @@ -170,7 +182,11 @@ static const struct gpio __led_5 = { &gpio_fp }; +#ifdef TEST_APP +static const struct driver led_5 = { +#else const struct driver led_5 = { +#endif DRIVER_TYPE_GPIO, &__led_5, }; @@ -198,7 +214,11 @@ static const struct gpio __led_6 = { &gpio_fp }; +#ifdef TEST_APP +static const struct driver led_6 = { +#else const struct driver led_6 = { +#endif DRIVER_TYPE_GPIO, &__led_6, }; diff --git a/source/firmware/kernel/include/list.h b/source/firmware/kernel/interface/list.h similarity index 100% rename from source/firmware/kernel/include/list.h rename to source/firmware/kernel/interface/list.h diff --git a/source/firmware/kernel/interface/shell.h b/source/firmware/kernel/interface/shell.h new file mode 100644 index 0000000..81fd032 --- /dev/null +++ b/source/firmware/kernel/interface/shell.h @@ -0,0 +1,22 @@ +/* + * shell.h + * + * Created on: Aug 1, 2016 + * Author: tkl + */ + +#ifndef SOURCE_FIRMWARE_KERNEL_INTERFACE_SHELL_H_ +#define SOURCE_FIRMWARE_KERNEL_INTERFACE_SHELL_H_ + +typedef void *(*command_callback)(const char*); + +struct command { + const char *command; + const command_callback command_callback; + struct list_node item; +}; + +int shell_init(const struct driver *shell_device); +int shell_add_command(struct command *command); + +#endif /* SOURCE_FIRMWARE_KERNEL_INTERFACE_SHELL_H_ */ diff --git a/source/firmware/kernel/shell.c b/source/firmware/kernel/shell.c new file mode 100644 index 0000000..0cfdba2 --- /dev/null +++ b/source/firmware/kernel/shell.c @@ -0,0 +1,85 @@ +/* + * shell.c + * + * Created on: Aug 1, 2016 + * Author: tkl + */ + +#include +#include +#include + +#include "stack.h" +#include "queue.h" +#include "driver.h" +#include "kernel.h" +#include "list.h" +#include "shell.h" + +struct shell_object { + struct list command_list; + const struct driver *shell_device; +}; + +struct shell_object shell_object; + +#define RX_STACK_SIZE 256 +stack_t rx_stack[RX_STACK_SIZE]; +struct thread_context rx_thread; + +static void parse(const char *buffer, unsigned int len) +{ + if(NULL == buffer) + return; + struct list_node *it = shell_object.command_list.front; + while(it != NULL) { + struct command *cmd = (struct command *)it->data; + if(strstr(buffer, cmd->command)) { + cmd->command_callback(buffer); + return; + } + it = it->next; + } +} + +static void rx_func(void *arg) +{ + char buffer[81]; + unsigned int index = 0; + int ret = 0; + open(shell_object.shell_device); + while(1) { + ret = read(shell_object.shell_device, &buffer[index], + sizeof(buffer) / sizeof(buffer[0]) - index - 1); + if(ret) { + write(shell_object.shell_device, &buffer[index], ret); // echo + if((buffer[index + ret - 1] == '\n') || (buffer[index + ret - 1] == '\r')) { + buffer[index + ret - 1] = '\n'; + parse(buffer, index + ret); + buffer[index + ret] = '\0'; + index = 0; + } + else + index += ret; + } + } +} + +int shell_init(const struct driver *shell_device) +{ + if(NULL == shell_device) + return -1; + list_init(&shell_object.command_list); + shell_object.shell_device = shell_device; + thread_create(&rx_thread, rx_stack, RX_STACK_SIZE, rx_func, NULL, THREAD_PRIO_LOW); + return 0; +} + +int shell_add_command(struct command *command) +{ + if(NULL == command) + return -1; + command->item.data = (unsigned int) command; + list_add(&shell_object.command_list, &command->item); + return 1; +} diff --git a/source/test/shell/main.c b/source/test/shell/main.c new file mode 100644 index 0000000..a1c4210 --- /dev/null +++ b/source/test/shell/main.c @@ -0,0 +1,39 @@ +/* + * main.c + * + * Created on: Aug 2, 2016 + * Author: tkl + */ + +#include + +#include "driver.h" +#include "board.h" +#include "stack.h" +#include "queue.h" +#include "kernel.h" +#include "driver.h" +#include "list.h" +#include "shell.h" + +void *uname_fct(const char *line) +{ + if(NULL == line) + return NULL; + + return NULL; +} + +static struct command cmd = { + .command = "uname", + .command_callback = uname_fct +}; + +int main(void) +{ + shell_init(&uart_1); + shell_add_command(&cmd); + schedule_start(); + + return 0; +} diff --git a/source/test/shell/shell.mk b/source/test/shell/shell.mk new file mode 100644 index 0000000..d07baa2 --- /dev/null +++ b/source/test/shell/shell.mk @@ -0,0 +1,4 @@ +CHECK_FOLDER += source/test/shell +SUB_FOLDER += source/test/shell +INCLUDES += source/test/shell +DOC_SRC += source/test/shell diff --git a/source/test/test.mk b/source/test/test.mk new file mode 100644 index 0000000..910224c --- /dev/null +++ b/source/test/test.mk @@ -0,0 +1,3 @@ +ifeq ($(TEST_APP), shell) +include source/test/shell/shell.mk +endif \ No newline at end of file