diff --git a/.cproject b/.cproject index 52959df..9689b1e 100755 --- a/.cproject +++ b/.cproject @@ -19,26 +19,26 @@ - + @@ -70,22 +70,22 @@ diff --git a/.gitignore b/.gitignore index aa8da2e..fcb85fe 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -release/ -.settings/ +release +.settings diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a5a8bd3..b25311a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,67 +1,31 @@ - - variables: -# PRODUCT_NAME: "AG" -# PRODUCT_VARIANT: "NA" -# PRODUCT_VARIANT: "EU" -# PRODUCT_VARIANT: "CN" -# PROJECT_VERSION: "10" -# SW_MAJOR: "1" -# SW_MINOR: "3" - + SW_MAJOR: "0" + SW_MINOR: "1" + APP: "engine_control" before_script: - "echo $CI_BUILD_ID" - "echo $CI_BUILD_REF_NAME" stages: - - check - build - - test -# - deploy + - deploy build_job: script: - - "make all BOARD=stm32f4-discovery DEBUG=y" + - "make all BOARD=stm32f4-discovery" stage: build except: - /^release/.*$/ -check_job: +deploy_job: + stage: deploy script: - - "make check BOARD=stm32f4-discovery DEBUG=y" - stage: check - -test_job: - script: - - "python source/scripts/get_history.py" - - "make install BOARD=stm32f4-discovery DEBUG=y" - stage: test - -#int_release_job: -# script: -# - "cd top_agricola/core" -# - "./generate_ci_makefile.py" -# - "make -f Makefile_ci.gen all" -# - "cd ci" -# - "./deploy_release.py -t rc" -# stage: deploy -# only: -# - /^release/.*$/ -# except: -# - tags - -#ext_release_job: -# script: -# - "cd top_agricola/core" -# - "./generate_ci_makefile.py" -# - "make -f Makefile_ci.gen all" -# - "cd ci" -# - "./deploy_release.py -t r" -# stage: deploy -# only: -# - /^release/174_AG.*$/ -# except: -# - branches - + - "source/scripts/release_number.py" + - "make deploy BOARD=stm32f4-discovery" + artifacts: + paths: + - ./*.xz + only: + - tags diff --git a/Makefile b/Makefile index d435fa4..6f18835 100755 --- a/Makefile +++ b/Makefile @@ -1,43 +1,43 @@ -############################################################## -# -############################################################## - include config/make/rules.mk +APP ?= engine_control + +# version numbering deployed by ci deploy script - no necessary for local build +ifdef SW_MAJOR +VERSION := -$(SW_MAJOR).$(SW_MINOR).$(CI_BUILD_ID) +else +VERSION := +endif MAINFILE = $(EXE_DIR)/$(APP)$(ELF_EXT) BINFILE = $(EXE_DIR)/$(APP)$(BIN_EXT) HEXFILE = $(EXE_DIR)/$(APP)$(HEX_EXT) SIZEFILE = $(SIZE_DIR)/$(APP)$(SIZE_EXT) +MAP_FILE = $(MAP_DIR)/$(APP)$(MAP_EXT) + +DEPLOY_PACKET = $(APP)-$(ARCH)-$(BOARD)$(VERSION)$(DBG_EXT).tar.xz INCLUDES += $(SRC_DIR) -SUB_FOLDER := -CHECK_FOLDER := SOURCES := $(wildcard $(SRC_DIR)/*.c) -ASM_SOURCES := $(wildcard $(SRC_DIR)/*.s) OBJECTS = $(SOURCES:$(ROOT_DIR)/%.c=$(OBJ_DIR)/%.o) -ASM_OBJECTS = $(ASMSOURCES:$(ROOT_DIR)/%.s=$(OBJ_DIR)/%.o) DEPS = $(SOURCES:$(ROOT_DIR)/%.c=$(OBJ_DIR)/%.d) #include subfolders include source/application/application.mk SOURCES += $(foreach folder, $(SUB_FOLDER), $(wildcard $(ROOT_DIR)/$(folder)/*.c)) -CHECKSOURCES += $(foreach folder, $(CHECK_FOLDER), $(wildcard $(ROOT_DIR)/$(folder)/*.c)) -ASMSOURCES += $(foreach folder, $(SUB_FOLDER), $(wildcard $(ROOT_DIR)/$(folder)/*.s)) -all: check $(MAINFILE) +all: $(MAINFILE) -check: - $(CPPCHECK) $(CPPCHECK_FLAGS) $(CHECKSOURCES) +deploy: all + tar cvJf $(DEPLOY_PACKET) -C $(EXE_DIR) . - -$(MAINFILE): $(OBJECTS) $(ASM_OBJECTS) +$(MAINFILE): $(OBJECTS) @$(MKDIR) $(EXE_DIR) @$(MKDIR) $(MAP_DIR) @$(MKDIR) $(SIZE_DIR) - $(CC) $(CFLAGS) -L$(LIB_DIR) $(LDFLAGS) -o $(MAINFILE) $(OBJECTS) $(ASM_OBJECTS) $(addprefix -l, $(LIBS)) + $(CXX) $(GEN_FLAGS) $(L_FLAGS) -L$(LIB_DIR) -Wl,-Map,"$(MAP_FILE)" -o "$(MAINFILE)" $(OBJECTS) $(addprefix -l, $(LIBS)) $(OBJCOPY) $(MAINFILE) -O binary $(BINFILE) $(OBJCOPY) $(MAINFILE) -O ihex $(HEXFILE) $(NM) --size-sort --print-size $(MAINFILE) > $(SIZEFILE) @@ -48,13 +48,8 @@ $(MAINFILE): $(OBJECTS) $(ASM_OBJECTS) $(OBJ_DIR)/%.o: $(ROOT_DIR)/%.c @$(MKDIR) $(OBJ_DIR) @$(foreach folder, $(SUB_FOLDER), $(shell mkdir -p $(OBJ_DIR)/$(folder))) - $(call makedep,$<,$@,$(subst .o,.d,$@)) - $(CC) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR)/%.o: $(ROOT_DIR)/%.s - @$(MKDIR) $(OBJ_DIR) - @$(foreach folder, $(SUB_FOLDER), $(shell mkdir -p $(OBJ_DIR)/$(folder))) - $(CC) $(CFLAGS) -c $< -o $@ + $(call makedep,$<,$@,$(subst .o,.d,$@),$(GEN_FLAGS) $(C_FLAGS)) + $(CC) $(GEN_FLAGS) $(C_FLAGS) -c -o "$@" "$<" clean: $(foreach folder, $(SUB_FOLDER), $(shell rm -f $(OBJ_DIR)/$(folder)/*.o)) @@ -73,10 +68,6 @@ install: all $(PRE_PROGRAM) $(PROGRAM) -doc: - @$(MKDIR) $(DOC_DIR) - (cat $(DOXYFILE) ; echo "INPUT=$(DOC_SRC)" ; echo "OUTPUT_DIRECTORY=$(DOC_DIR)") | doxygen - - ifneq "$(MAKECMDGOALS)" "clean" -include $(DEPS) else diff --git a/config/linker/libs.ld b/config/linker/libs.ld new file mode 100644 index 0000000..70fea89 --- /dev/null +++ b/config/linker/libs.ld @@ -0,0 +1,8 @@ + +/* + * Placeholder to list other libraries required by the application. + +GROUP( +) + + */ diff --git a/config/linker/mem.ld b/config/linker/mem.ld new file mode 100644 index 0000000..e80fd60 --- /dev/null +++ b/config/linker/mem.ld @@ -0,0 +1,32 @@ +/* + * Memory Spaces Definitions. + * + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + * + * The values below can be addressed in further linker scripts + * using functions like 'ORIGIN(RAM)' or 'LENGTH(RAM)'. + */ + +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0 + EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0 + EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0 + EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0 + EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0 + MEMORY_ARRAY (xrw) : ORIGIN = 0x20002000, LENGTH = 32 +} + +/* + * For external ram use something like: + + RAM (xrw) : ORIGIN = 0x64000000, LENGTH = 2048K + + */ diff --git a/config/linker/sections.ld b/config/linker/sections.ld new file mode 100644 index 0000000..9ef139f --- /dev/null +++ b/config/linker/sections.ld @@ -0,0 +1,445 @@ +/* + * Default linker script for Cortex-M (it includes specifics for STM32F[34]xx). + * + * To make use of the multi-region initialisations, define + * OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS for the _startup.c file. + */ + +/* + * The '__stack' definition is required by crt0, do not remove it. + */ +__stack = ORIGIN(RAM) + LENGTH(RAM); + +_estack = __stack; /* STM specific definition */ + +/* + * Default stack sizes. + * These are used by the startup in order to allocate stacks + * for the different modes. + */ + +__Main_Stack_Size = 1024 ; + +PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ; + +__Main_Stack_Limit = __stack - __Main_Stack_Size ; + +/* "PROVIDE" allows to easily override these values from an + * object file or the command line. */ +PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ; + +/* + * There will be a link error if there is not this amount of + * RAM free at the end. + */ +_Minimum_Stack_Size = 256 ; + +/* + * Default heap definitions. + * The heap start immediately after the last statically allocated + * .sbss/.noinit section, and extends up to the main stack limit. + */ +PROVIDE ( _Heap_Begin = _end_noinit ) ; +PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ; + +/* + * The entry point is informative, for debuggers and simulators, + * since the Cortex-M vector points to it anyway. + */ +ENTRY(_start) + + +/* Sections Definitions */ + +SECTIONS +{ + /* + * For Cortex-M devices, the beginning of the startup code is stored in + * the .isr_vector section, which goes to FLASH. + */ + .isr_vector : ALIGN(4) + { + FILL(0xFF) + + __vectors_start = ABSOLUTE(.) ; + __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */ + KEEP(*(.isr_vector)) /* Interrupt vectors */ + + KEEP(*(.cfmconfig)) /* Freescale configuration words */ + + /* + * This section is here for convenience, to store the + * startup code at the beginning of the flash area, hoping that + * this will increase the readability of the listing. + */ + *(.after_vectors .after_vectors.*) /* Startup code and ISR */ + + } >FLASH + + .inits : ALIGN(4) + { + /* + * Memory regions initialisation arrays. + * + * Thee are two kinds of arrays for each RAM region, one for + * data and one for bss. Each is iterrated at startup and the + * region initialisation is performed. + * + * The data array includes: + * - from (LOADADDR()) + * - region_begin (ADDR()) + * - region_end (ADDR()+SIZEOF()) + * + * The bss array includes: + * - region_begin (ADDR()) + * - region_end (ADDR()+SIZEOF()) + * + * WARNING: It is mandatory that the regions are word aligned, + * since the initialisation code works only on words. + */ + + __data_regions_array_start = .; + + LONG(LOADADDR(.data)); + LONG(ADDR(.data)); + LONG(ADDR(.data)+SIZEOF(.data)); + + LONG(LOADADDR(.data_CCMRAM)); + LONG(ADDR(.data_CCMRAM)); + LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM)); + + __data_regions_array_end = .; + + __bss_regions_array_start = .; + + LONG(ADDR(.bss)); + LONG(ADDR(.bss)+SIZEOF(.bss)); + + LONG(ADDR(.bss_CCMRAM)); + LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM)); + + __bss_regions_array_end = .; + + /* End of memory regions initialisation arrays. */ + + /* + * These are the old initialisation sections, intended to contain + * naked code, with the prologue/epilogue added by crti.o/crtn.o + * when linking with startup files. The standalone startup code + * currently does not run these, better use the init arrays below. + */ + KEEP(*(.init)) + KEEP(*(.fini)) + + . = ALIGN(4); + + /* + * The preinit code, i.e. an array of pointers to initialisation + * functions to be performed before constructors. + */ + PROVIDE_HIDDEN (__preinit_array_start = .); + + /* + * Used to run the SystemInit() before anything else. + */ + KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*)) + + /* + * Used for other platform inits. + */ + KEEP(*(.preinit_array_platform .preinit_array_platform.*)) + + /* + * The application inits. If you need to enforce some order in + * execution, create new sections, as before. + */ + KEEP(*(.preinit_array .preinit_array.*)) + + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + + /* + * The init code, i.e. an array of pointers to static constructors. + */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + + /* + * The fini code, i.e. an array of pointers to static destructors. + */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + } >FLASH + + /* + * For some STRx devices, the beginning of the startup code + * is stored in the .flashtext section, which goes to FLASH. + */ + .flashtext : ALIGN(4) + { + *(.flashtext .flashtext.*) /* Startup code */ + } >FLASH + + + /* + * The program code is stored in the .text section, + * which goes to FLASH. + */ + .text : ALIGN(4) + { + *(.text .text.*) /* all remaining code */ + + /* read-only data (constants) */ + *(.rodata .rodata.* .constdata .constdata.*) + + *(vtable) /* C++ virtual tables */ + + KEEP(*(.eh_frame*)) + + /* + * Stub sections generated by the linker, to glue together + * ARM and Thumb code. .glue_7 is used for ARM code calling + * Thumb code, and .glue_7t is used for Thumb code calling + * ARM code. Apparently always generated by the linker, for some + * architectures, so better leave them here. + */ + *(.glue_7) + *(.glue_7t) + + } >FLASH + + /* ARM magic sections */ + .ARM.extab : ALIGN(4) + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + . = ALIGN(4); + __exidx_start = .; + .ARM.exidx : ALIGN(4) + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + . = ALIGN(4); + _etext = .; + __etext = .; + + /* MEMORY_ARRAY */ + /* + .ROarraySection : + { + *(.ROarraySection .ROarraySection.*) + } >MEMORY_ARRAY + */ + + /* + * The secondary initialised data section. + */ + .data_CCMRAM : ALIGN(4) + { + FILL(0xFF) + *(.data.CCMRAM .data.CCMRAM.*) + . = ALIGN(4) ; + } > CCMRAM AT>FLASH + + /* + * This address is used by the startup code to + * initialise the .data section. + */ + _sidata = LOADADDR(.data); + + /* + * The initialised data section. + * + * The program executes knowing that the data is in the RAM + * but the loader puts the initial values in the FLASH (inidata). + * It is one task of the startup to copy the initial values from + * FLASH to RAM. + */ + .data : ALIGN(4) + { + FILL(0xFF) + /* This is used by the startup code to initialise the .data section */ + _sdata = . ; /* STM specific definition */ + __data_start__ = . ; + *(.data_begin .data_begin.*) + + *(.data .data.*) + + *(.data_end .data_end.*) + . = ALIGN(4); + + /* This is used by the startup code to initialise the .data section */ + _edata = . ; /* STM specific definition */ + __data_end__ = . ; + + } >RAM AT>FLASH + + /* + * The uninitialised data sections. NOLOAD is used to avoid + * the "section `.bss' type changed to PROGBITS" warning + */ + + /* The secondary uninitialised data section. */ + .bss_CCMRAM (NOLOAD) : ALIGN(4) + { + *(.bss.CCMRAM .bss.CCMRAM.*) + } > CCMRAM + + /* The primary uninitialised data section. */ + .bss (NOLOAD) : ALIGN(4) + { + __bss_start__ = .; /* standard newlib definition */ + _sbss = .; /* STM specific definition */ + *(.bss_begin .bss_begin.*) + + *(.bss .bss.*) + *(COMMON) + + *(.bss_end .bss_end.*) + . = ALIGN(4); + __bss_end__ = .; /* standard newlib definition */ + _ebss = . ; /* STM specific definition */ + } >RAM + + .noinit_CCMRAM (NOLOAD) : ALIGN(4) + { + *(.noinit.CCMRAM .noinit.CCMRAM.*) + } > CCMRAM + + .noinit (NOLOAD) : ALIGN(4) + { + _noinit = .; + + *(.noinit .noinit.*) + + . = ALIGN(4) ; + _end_noinit = .; + } > RAM + + /* Mandatory to be word aligned, _sbrk assumes this */ + PROVIDE ( end = _end_noinit ); /* was _ebss */ + PROVIDE ( _end = _end_noinit ); + PROVIDE ( __end = _end_noinit ); + PROVIDE ( __end__ = _end_noinit ); + + /* + * Used for validation only, do not allocate anything here! + * + * This is just to check that there is enough RAM left for the Main + * stack. It should generate an error if it's full. + */ + ._check_stack : ALIGN(4) + { + . = . + _Minimum_Stack_Size ; + } >RAM + + /* + * The FLASH Bank1. + * The C or assembly source must explicitly place the code + * or data there using the "section" attribute. + */ + .b1text : ALIGN(4) + { + *(.b1text) /* remaining code */ + *(.b1rodata) /* read-only data (constants) */ + *(.b1rodata.*) + } >FLASHB1 + + /* + * The EXTMEM. + * The C or assembly source must explicitly place the code or data there + * using the "section" attribute. + */ + + /* EXTMEM Bank0 */ + .eb0text : ALIGN(4) + { + *(.eb0text) /* remaining code */ + *(.eb0rodata) /* read-only data (constants) */ + *(.eb0rodata.*) + } >EXTMEMB0 + + /* EXTMEM Bank1 */ + .eb1text : ALIGN(4) + { + *(.eb1text) /* remaining code */ + *(.eb1rodata) /* read-only data (constants) */ + *(.eb1rodata.*) + } >EXTMEMB1 + + /* EXTMEM Bank2 */ + .eb2text : ALIGN(4) + { + *(.eb2text) /* remaining code */ + *(.eb2rodata) /* read-only data (constants) */ + *(.eb2rodata.*) + } >EXTMEMB2 + + /* EXTMEM Bank0 */ + .eb3text : ALIGN(4) + { + *(.eb3text) /* remaining code */ + *(.eb3rodata) /* read-only data (constants) */ + *(.eb3rodata.*) + } >EXTMEMB3 + + + /* After that there are only debugging sections. */ + + /* This can remove the debugging information from the standard libraries */ + /* + DISCARD : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* + * DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. + */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/config/linker/stm32_flash.ld b/config/linker/stm32_flash.ld deleted file mode 100755 index 7cfdc96..0000000 --- a/config/linker/stm32_flash.ld +++ /dev/null @@ -1,170 +0,0 @@ -/* -***************************************************************************** -** -** 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 f09f8a2..c12c972 100755 --- a/config/make/rules.mk +++ b/config/make/rules.mk @@ -12,18 +12,6 @@ LIB_DIR += $(SRC_DIR)/os/$(DBG_REL_DIR) OS_LIB = kosmos-$(ARCH)-$(BOARD)$(DBG_EXT) LIBS += $(OS_LIB) -CFLAGS += \ - -O$(OPTIM) \ - $(addprefix -I, $(INCLUDES)) \ - -Wall - -CPPCHECK_FLAGS += \ - --template=gcc \ - --error-exitcode=1 \ - --enable=warning,performance,information,style \ - --inline-suppr \ - $(addprefix -I, $(INCLUDES)) - include $(ROOT_DIR)/config/make/tools.mk SRC_DIR = $(ROOT_DIR)/source @@ -48,23 +36,15 @@ HEX_EXT = .hex LIB_EXT = .a SIZE_EXT = .size TEST_EXT = +MAP_EXT = .map DOXYFILE=$(ROOT_DIR)/config/doxygen/Doxyfile define makedep - $(CC) -MM \ - -MF $3 \ - -MP \ - -MT $2 \ - $(CFLAGS) \ - $1 -endef - -define maketestdep - $(NATIVE_CC) -MM \ - -MF $3 \ - -MP \ - -MT $2 \ - $(TEST_CFLAGS) \ + $(CC) -MM \ + -MF $3 \ + -MP \ + -MT $2 \ + $4 \ $1 endef diff --git a/config/make/stm32f4xx.mk b/config/make/stm32f4xx.mk index 39113d7..7394a12 100644 --- a/config/make/stm32f4xx.mk +++ b/config/make/stm32f4xx.mk @@ -6,53 +6,81 @@ endif ifeq ($(BOARD), stm32f4-discovery) CFLAGS += -DBOARD_STM32F4_DISCOVERY endif -CROSS_COMPILE=arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- + +INCLUDES += source/system/stm32f4xx +SUB_FOLDER += source/system/stm32f4xx INCLUDES += \ - /usr/lib/arm-none-eabi/include \ - /usr/lib/gcc/arm-none-eabi/4.8/include + /opt/gcc-arm-none-eabi-5_4-2016q2/arm-none-eabi/include \ + /opt/gcc-arm-none-eabi-5_4-2016q2/lib/gcc/arm-none-eabi/5.4.1/include + +GEN_FLAGS += \ + -mcpu=cortex-m4 \ + -mthumb \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -O$(OPTIM) \ + -fmessage-length=0 \ + -fsigned-char \ + -ffunction-sections \ + -fdata-sections \ + -ffreestanding \ + -fno-move-loop-invariants \ + -Werror \ + -Wunused \ + -Wuninitialized \ + -Wall \ + -Wextra \ + -Wmissing-declarations \ + -Wconversion \ + -Wpointer-arith \ + -Wpadded \ + -Wshadow \ + -Wlogical-op \ + -Waggregate-return \ + -Wfloat-equal + +C_FLAGS += \ + -DDEBUG \ + -DUSE_FULL_ASSERT \ + -DTRACE \ + -DOS_USE_TRACE_SEMIHOSTING_DEBUG \ + -DSTM32F407xx \ + -DUSE_HAL_DRIVER \ + -DHSE_VALUE=8000000 \ + $(addprefix -I, $(INCLUDES)) \ + -std=gnu11 \ + -Wmissing-prototypes \ + -Wstrict-prototypes \ + -Wbad-function-cast \ + -Wno-bad-function-cast \ + -Wno-conversion \ + -Wno-sign-conversion \ + -Wno-unused-parameter \ + -Wno-sign-compare \ + -Wno-missing-prototypes \ + -Wno-missing-declarations + +L_FLAGS := \ + -T mem.ld \ + -T libs.ld \ + -T sections.ld \ + -nostartfiles \ + -Xlinker --gc-sections \ + -L"config/linker" \ + --specs=nano.specs +# --specs=nosys.specs ifeq ($(DEBUG),y) -OPTIM = 0 -CFLAGS += -g +OPTIM = g +GEN_FLAGS += -g3 DBG_EXT = -dbg else OPTIM = s -LDFLAGS += -s DBG_EXT = endif -CFLAGS += \ - -mthumb \ - -T $(ROOT_DIR)/config/linker/stm32_flash.ld \ - -D USE_STDPERIPH_DRIVER\ - -D VECT_TAB_FLASH\ - -D GCC_ARMCM4\ - -D THUMB_INTERWORK\ - -D PACK_STRUCT_END=__attribute\(\(packed\)\)\ - -D ALIGN_STRUCT_END=__attribute\(\(aligned\(4\)\)\)\ - -mcpu=cortex-m4 \ - -mfpu=fpv4-sp-d16 \ - -mfloat-abi=softfp \ - -fdata-sections \ - -ffunction-sections -# -D inline= -mthumb\ - -CPPCHECK_FLAGS += \ - -D USE_STDPERIPH_DRIVER\ - -D VECT_TAB_FLASH\ - -D GCC_ARMCM4\ - -D THUMB_INTERWORK\ - -D PACK_STRUCT_END=__attribute\(\(packed\)\)\ - -D ALIGN_STRUCT_END=__attribute\(\(aligned\(4\)\)\)\ - -D __thumb__ \ - --check-config - -LDFLAGS=\ - -Wl,--gc-sections \ - -Xlinker -M > $(MAP_DIR)/$(APP).map - -ASFLAGS=-mapcs-32 -g ARFLAGS=rcs OOCD_IMAGE=$(BINFILE) diff --git a/source/application/application.mk b/source/application/application.mk index e8db916..ac11f41 100755 --- a/source/application/application.mk +++ b/source/application/application.mk @@ -1,4 +1,4 @@ CHECK_FOLDER += source/application SUB_FOLDER += source/application -INCLUDES += source/application +INCLUDES += source/application/include DOC_SRC += source/application diff --git a/source/application/drive_ctrl.c b/source/application/drive_ctrl.c new file mode 100644 index 0000000..c232a1d --- /dev/null +++ b/source/application/drive_ctrl.c @@ -0,0 +1,125 @@ +/* + * drive_ctrl.c + * + * Created on: Aug 10, 2016 + * Author: tkl + */ + +#include + +#include "driver.h" +#include "board_devices.h" +#include "engines.h" + +#include "drive_ctrl.h" + +struct drive_ctrl { + struct engine_ctrl *left_forward; + struct engine_ctrl *left_backward; + struct engine_ctrl *right_forward; + struct engine_ctrl *right_backward; +}; + +struct drive_ctrl_object { + unsigned int current_speed; +}; + +static struct drive_ctrl drive_ctrl = { + .left_forward = &left_forward, + .left_backward = &left_backward, + .right_forward = &right_forward, + .right_backward = &right_backward, +}; + +static struct drive_ctrl_object drive_ctrl_object = { + .current_speed = 50, /* % */ +}; + +int drive_ctrl_init(void) +{ + unsigned int duty = 0; + + /* open enable pins */ + drv_open(drive_ctrl.left_forward->enable); + drv_write(drive_ctrl.left_forward->enable, "0", 1); + drv_open(drive_ctrl.left_backward->enable); + drv_write(drive_ctrl.left_backward->enable, "0", 1); + drv_open(drive_ctrl.right_forward->enable); + drv_write(drive_ctrl.right_forward->enable, "0", 1); + drv_open(drive_ctrl.right_backward->enable); + drv_write(drive_ctrl.right_backward->enable, "0", 1); + + /* open pwm's */ + drv_open(drive_ctrl.left_backward->pwm); + drv_ioctl(drive_ctrl.left_backward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_open(drive_ctrl.left_forward->pwm); + drv_ioctl(drive_ctrl.left_forward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_open(drive_ctrl.right_backward->pwm); + drv_ioctl(drive_ctrl.right_backward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + drv_open(drive_ctrl.right_forward->pwm); + drv_ioctl(drive_ctrl.right_forward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&duty); + + /* enable enable pins */ + drv_write(drive_ctrl.left_forward->enable, "1", 1); + drv_write(drive_ctrl.left_backward->enable, "1", 1); + drv_write(drive_ctrl.right_forward->enable, "1", 1); + drv_write(drive_ctrl.right_backward->enable, "1", 1); + + return 0; +} + +static unsigned int calc_speed_front(int speed_percent) +{ + unsigned int speed_front = 0; + if(speed_percent > 0) { + if(speed_percent > 100) + speed_front = 100; + else + speed_front = (unsigned int) speed_percent; + } + return speed_front; +} + +static unsigned int calc_speed_back(int speed_percent) +{ + unsigned int speed_back = 0; + if(speed_percent < 0) { + if(speed_percent < -100) + speed_back = 100; + else + speed_back = (unsigned int) abs(speed_percent); + } + return speed_back; +} + +int drive_ctrl_set_speed_left(int speed_percent) +{ + unsigned int front_speed = calc_speed_front(speed_percent); + unsigned int back_speed = calc_speed_back(speed_percent); + int ret = drv_ioctl(drive_ctrl.left_backward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&back_speed); + ret |= drv_ioctl(drive_ctrl.left_forward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&front_speed); + + return ret; +} + +int drive_ctrl_set_speed_right(int speed_percent) +{ + unsigned int front_speed = calc_speed_front(speed_percent); + unsigned int back_speed = calc_speed_back(speed_percent); + int ret = drv_ioctl(drive_ctrl.right_backward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&back_speed); + ret |= drv_ioctl(drive_ctrl.right_forward->pwm, IOCTL_PWM_SET_DUTY_CYCLE, (const void *)&front_speed); + + return ret; +} + +int drive_ctrl_set_speed_value(int speed_percent) +{ + drive_ctrl_object.current_speed = speed_percent; + + return 0; +} + +int drive_ctrl_get_speed_value(void) +{ + return drive_ctrl_object.current_speed; +} diff --git a/source/application/include/drive_ctrl.h b/source/application/include/drive_ctrl.h new file mode 100644 index 0000000..f499a5b --- /dev/null +++ b/source/application/include/drive_ctrl.h @@ -0,0 +1,19 @@ +/* + * drive_ctrl.h + * + * Created on: Aug 10, 2016 + * Author: tkl + */ + +#ifndef SOURCE_APPLICATION_INCLUDE_DRIVE_CTRL_H_ +#define SOURCE_APPLICATION_INCLUDE_DRIVE_CTRL_H_ + +int drive_ctrl_init(void); + +int drive_ctrl_set_speed_left(int speed_percent); +int drive_ctrl_set_speed_right(int speed_percent); +int drive_ctrl_set_speed_value(int speed_percent); +int drive_ctrl_get_speed_value(void); + + +#endif /* SOURCE_APPLICATION_INCLUDE_DRIVE_CTRL_H_ */ diff --git a/source/application/include/engines.h b/source/application/include/engines.h new file mode 100644 index 0000000..8957632 --- /dev/null +++ b/source/application/include/engines.h @@ -0,0 +1,36 @@ +/* + * engines.h + * + * Created on: Aug 10, 2016 + * Author: tkl + */ + +#ifndef SOURCE_APPLICATION_INCLUDE_ENGINES_H_ +#define SOURCE_APPLICATION_INCLUDE_ENGINES_H_ + +struct engine_ctrl { + const struct driver *pwm; + const struct driver *enable; +}; + +static struct engine_ctrl right_forward = { + .pwm = &pwm_2, + .enable = &gpio_c0, +}; + +static struct engine_ctrl right_backward = { + .pwm = &pwm_1, + .enable = &gpio_c1, +}; + +static struct engine_ctrl left_forward = { + .pwm = &pwm_4, + .enable = &gpio_c2, +}; + +static struct engine_ctrl left_backward = { + .pwm = &pwm_3, + .enable = &gpio_c3, +}; + +#endif /* SOURCE_APPLICATION_INCLUDE_ENGINES_H_ */ diff --git a/source/application/include/shell_commands.h b/source/application/include/shell_commands.h new file mode 100644 index 0000000..4ba9527 --- /dev/null +++ b/source/application/include/shell_commands.h @@ -0,0 +1,13 @@ +/* + * shell_commands.h + * + * Created on: Aug 10, 2016 + * Author: tkl + */ + +#ifndef SOURCE_APPLICATION_SHELL_COMMANDS_H_ +#define SOURCE_APPLICATION_SHELL_COMMANDS_H_ + +int shell_commands_init(void); + +#endif /* SOURCE_APPLICATION_SHELL_COMMANDS_H_ */ diff --git a/source/application/include/version.h b/source/application/include/version.h new file mode 100644 index 0000000..d351bc1 --- /dev/null +++ b/source/application/include/version.h @@ -0,0 +1,9 @@ +/* Release number include file */ + +#ifndef VERSION_H +#define VERSION_H + +#define MAJOR_VERSION "unknown" +#define MINOR_VERSION "unknown" +#define BUILD_NUMBER "unknown" +#endif /* VERSION_H */ diff --git a/source/application/main.c b/source/application/main.c index 7b3fe36..4544360 100644 --- a/source/application/main.c +++ b/source/application/main.c @@ -1,57 +1,25 @@ -#include #include -#include -#include -#include +#include -#include "driver.h" #include "board_devices.h" #include "stack.h" #include "queue.h" #include "kernel.h" #include "driver.h" +#include "list.h" +#include "shell.h" +#include "shell_commands.h" +#include "drive_ctrl.h" -#define STACK_SIZE 256 -stack_t tc_1_stack[STACK_SIZE]; -struct thread_context tc_1; - -void task1(void *arg) -{ - char rd = '0'; - open(&led_4); - write(&led_4, &rd, 1); - while(1) { - sleep_ms(1000); - read(&led_4, &rd, 1); - if(rd == '0') - rd = '1'; - else - rd = '0'; - write(&led_4, &rd, 1); - write(&uart_1, "Driver test\r\n", 13); - } -} - -char rx_buf[80]; -void task2(void *arg) -{ - while(1) { - int i = read(&uart_1, rx_buf, 80); - if(i > 0) { - write(&uart_1, rx_buf, i); - } - } -} - -stack_t tc_2_stack[STACK_SIZE]; -struct thread_context tc_2; int main(void) { - open(&uart_1); - thread_create(&tc_1, tc_1_stack, STACK_SIZE, task1, NULL, THREAD_PRIO_LOW); - thread_create(&tc_2, tc_2_stack, STACK_SIZE, task2, NULL, THREAD_PRIO_LOW); + drive_ctrl_init(); + shell_init(&uart_1); + shell_commands_init(); - schedule_start(); + while(1) { + sleep_ms(1000); + } return 0; } diff --git a/source/application/shell_commands.c b/source/application/shell_commands.c new file mode 100644 index 0000000..0cb89f8 --- /dev/null +++ b/source/application/shell_commands.c @@ -0,0 +1,176 @@ +/* + * shell_commands.c + * + * Created on: Aug 10, 2016 + * Author: tkl + */ +#include +#include + +#include "list.h" +#include "driver.h" +#include "shell.h" +#include "drive_ctrl.h" +#include "version.h" + +static void *drive_turn_right_cb(const char *param); +static void *drive_turn_left_cb(const char *param); +static void *drive_boost_cb(const char *param); +static void *drive_retard_cb(const char *param); +static void *drive_halt_cb(const char *param); +static void *drive_forward_cb(const char *param); +static void *drive_backward_cb(const char *param); +static void *app_version(const char *param); + +static struct command cmd_app_version = { + .command = "version", + .description = "Get application version.", + .command_callback = app_version, +}; + +static struct command drive_forward = { + .command = "f", + .description = "Start driving forward with preset speed.", + .command_callback = drive_forward_cb, +}; + +static struct command drive_backward = { + .command = "b", + .description = "Start driving backward with preset speed.", + .command_callback = drive_backward_cb, +}; + +static struct command drive_halt = { + .command = "h", + .description = "Stop driving.", + .command_callback = drive_halt_cb, +}; + +static struct command drive_boost = { + .command = "+", + .description = "Boost speed.", + .command_callback = drive_boost_cb, +}; + +static struct command drive_retard = { + .command = "-", + .description = "Retard speed", + .command_callback = drive_retard_cb, +}; + +static struct command drive_turn_left = { + .command = "l", + .description = "Turn left.", + .command_callback = drive_turn_left_cb, +}; + +static struct command drive_turn_right = { + .command = "r", + .description = "Turn right", + .command_callback = drive_turn_right_cb, +}; + +int shell_commands_init(void) +{ + shell_add_command(&drive_forward); + shell_add_command(&drive_backward); + shell_add_command(&drive_boost); + shell_add_command(&drive_retard); + shell_add_command(&drive_halt); + shell_add_command(&drive_turn_left); + shell_add_command(&drive_turn_right); + shell_add_command(&cmd_app_version); + + return 0; +} + +static void *drive_turn_right_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + drive_ctrl_set_speed_left(abs(speed)); + if(speed > 0) + speed *= -1; + drive_ctrl_set_speed_right(speed); + + return NULL; +} + +static void *drive_turn_left_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + drive_ctrl_set_speed_right(abs(speed)); + if(speed > 0) + speed *= -1; + drive_ctrl_set_speed_left(speed); + + return NULL; +} + +static void *drive_boost_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + speed += 10; + drive_ctrl_set_speed_value(speed); + drive_ctrl_set_speed_left(speed); + drive_ctrl_set_speed_right(speed); + + return NULL; +} + +static void *drive_retard_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + speed -= 10; + drive_ctrl_set_speed_value(speed); + drive_ctrl_set_speed_left(speed); + drive_ctrl_set_speed_right(speed); + + return NULL; +} + +static void *drive_halt_cb(const char *param) +{ + drive_ctrl_set_speed_left(0); + drive_ctrl_set_speed_right(0); + + return NULL; +} + +static void *drive_forward_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + if(speed < 0) + speed = abs(speed); + drive_ctrl_set_speed_value(speed); + drive_ctrl_set_speed_left(speed); + drive_ctrl_set_speed_right(speed); + + return NULL; +} + +static void *drive_backward_cb(const char *param) +{ + int speed = drive_ctrl_get_speed_value(); + if(speed > 0) + speed *= -1; + drive_ctrl_set_speed_value(speed); + drive_ctrl_set_speed_left(speed); + drive_ctrl_set_speed_right(speed); + + return NULL; +} + +static void *app_version(const char *param) +{ +#if 0 + char *greeter = "engine_control version: "; + + drv_write(shell_object.shell_device, greeter, strlen(greeter)); + drv_write(shell_object.shell_device, MAJOR_VERSION, strlen(MAJOR_VERSION)); + drv_write(shell_object.shell_device, ".", 1); + drv_write(shell_object.shell_device, MINOR_VERSION, strlen(MINOR_VERSION)); + drv_write(shell_object.shell_device, ".", 1); + drv_write(shell_object.shell_device, BUILD_NUMBER, strlen(BUILD_NUMBER)); +#endif + return NULL; +} diff --git a/source/os/debug/include/board_devices.h b/source/os/debug/include/board_devices.h deleted file mode 100644 index 16ace5b..0000000 --- a/source/os/debug/include/board_devices.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Board devices include file */ - -#ifndef BOARD_DEVICES_H -#define BOARD_DEVICES_H - -extern const struct driver uart_1; -extern const struct driver led_3; -extern const struct driver led_4; -extern const struct driver led_5; -extern const struct driver led_6; - -#endif /* BOARD_DEVICES_H */ diff --git a/source/os/debug/include/driver.h b/source/os/debug/include/driver.h deleted file mode 100644 index ee82abf..0000000 --- a/source/os/debug/include/driver.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * driver.h - * - * Created on: Jul 27, 2016 - * Author: tkl - */ - -#ifndef SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ -#define SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ - -enum driver_type { - DRIVER_TYPE_ADC, - DRIVER_TYPE_GPIO, - DRIVER_TYPE_I2C, - DRIVER_TYPE_RTC, - DRIVER_TYPE_SPI, - DRIVER_TYPE_UART -}; - -struct driver { - enum driver_type driver_type; - const void *device_driver; -}; - -int open(const struct driver *driver); -int close(const struct driver *driver); -int read(const struct driver *driver, char *buffer, int len); -int write(const struct driver *driver, const char *buffer, int len); - -#endif /* SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ */ diff --git a/source/os/debug/include/kernel.h b/source/os/debug/include/kernel.h deleted file mode 100644 index b9d4520..0000000 --- a/source/os/debug/include/kernel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * kernel.h - * - * Created on: Jul 28, 2016 - * Author: tkl - */ - -#ifndef SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_ -#define SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_ - -void schedule_start(void); - -enum thread_priority { - THREAD_PRIO_IDLE = 0, - THREAD_PRIO_LOW, - THREAD_PRIO_MEDIUM, - THREAD_PRIO_HIGH -}; - -enum thread_status { - THREAD_STATUS_INIT = 0, - THREAD_STATUS_EXECUTING, - THREAD_STATUS_WAITING, - THREAD_STATUS_SLEEPING, - THREAD_STATUS_BLOCKING -}; - -struct thread_context { - stack_t *sp; /**< thread's stack pointer */ - stack_t *stack; /**< thread's stack start address */ - unsigned int stack_size; /**< thread's stack size */ - unsigned int pid; /**< thread's process id */ - enum thread_priority priority; /**< thread's priority */ - enum thread_status status; /**< thread's status */ - unsigned long next_executing_time; - void *wakeup_blocking_source; - struct queue_node sem_queue_node; -}; - -struct thread_context *thread_create( - struct thread_context *thread, - stack_t *stack, - unsigned int stack_size, - void (*thread_func)(void *), - void *arg, - enum thread_priority priority); - -void thread_exit(void); -void sleep_ms(unsigned int ms); - -#endif /* SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_ */ diff --git a/source/os/debug/include/queue.h b/source/os/debug/include/queue.h deleted file mode 100644 index 996ef90..0000000 --- a/source/os/debug/include/queue.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * queue.h - * - * Created on: Oct 25, 2015 - * Author: tkl - */ - -#ifndef QUEUE_H_ -#define QUEUE_H_ - -struct queue_node { - struct queue_node *next; - unsigned int data; -}; - -struct queue { - struct queue_node *front; - struct queue_node *rear; -}; - -int queue_init(struct queue *head); -int queue_push(struct queue *head, struct queue_node *node); -int queue_pop(struct queue *head, struct queue_node *node); -bool queue_is_empty(struct queue *head); - -#endif /* QUEUE_H_ */ diff --git a/source/os/debug/include/stack.h b/source/os/debug/include/stack.h deleted file mode 100644 index b792758..0000000 --- a/source/os/debug/include/stack.h +++ /dev/null @@ -1,8 +0,0 @@ -/* Stack include file */ - -#ifndef STACK_H -#define STACK_H - -typedef uint32_t stack_t; - -#endif /* STACK_H */ diff --git a/source/os/debug/libkosmos-arm-stm32f4-discovery-dbg.a b/source/os/debug/libkosmos-arm-stm32f4-discovery-dbg.a deleted file mode 100644 index d285e6a..0000000 Binary files a/source/os/debug/libkosmos-arm-stm32f4-discovery-dbg.a and /dev/null differ diff --git a/source/os/release/include/board_devices.h b/source/os/release/include/board_devices.h index 16ace5b..ec42636 100644 --- a/source/os/release/include/board_devices.h +++ b/source/os/release/include/board_devices.h @@ -3,10 +3,14 @@ #ifndef BOARD_DEVICES_H #define BOARD_DEVICES_H +extern const struct driver gpio_c0; +extern const struct driver gpio_c1; +extern const struct driver gpio_c2; +extern const struct driver gpio_c3; +extern const struct driver pwm_4; +extern const struct driver pwm_3; +extern const struct driver pwm_2; +extern const struct driver pwm_1; extern const struct driver uart_1; -extern const struct driver led_3; -extern const struct driver led_4; -extern const struct driver led_5; -extern const struct driver led_6; #endif /* BOARD_DEVICES_H */ diff --git a/source/os/release/include/driver.h b/source/os/release/include/driver.h index ee82abf..e91349d 100644 --- a/source/os/release/include/driver.h +++ b/source/os/release/include/driver.h @@ -8,23 +8,30 @@ #ifndef SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ #define SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ +#define IOCTL_PWM_SET_DUTY_CYCLE 0 + enum driver_type { DRIVER_TYPE_ADC, DRIVER_TYPE_GPIO, DRIVER_TYPE_I2C, + DRIVER_TYPE_PWM, DRIVER_TYPE_RTC, DRIVER_TYPE_SPI, DRIVER_TYPE_UART }; +#pragma pack(push) +#pragma pack(1) struct driver { enum driver_type driver_type; const void *device_driver; }; +#pragma pack(pop) -int open(const struct driver *driver); -int close(const struct driver *driver); -int read(const struct driver *driver, char *buffer, int len); -int write(const struct driver *driver, const char *buffer, int len); +int drv_open(const struct driver *driver); +int drv_close(const struct driver *driver); +int drv_read(const struct driver *driver, char *buffer, int len); +int drv_write(const struct driver *driver, const char *buffer, int len); +int drv_ioctl(const struct driver *driver, unsigned int cmd, const void *data); #endif /* SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ */ diff --git a/source/os/release/include/kernel.h b/source/os/release/include/kernel.h index b9d4520..e69f607 100644 --- a/source/os/release/include/kernel.h +++ b/source/os/release/include/kernel.h @@ -25,6 +25,8 @@ enum thread_status { THREAD_STATUS_BLOCKING }; +#pragma pack(push) +#pragma pack(1) struct thread_context { stack_t *sp; /**< thread's stack pointer */ stack_t *stack; /**< thread's stack start address */ @@ -36,6 +38,16 @@ struct thread_context { void *wakeup_blocking_source; struct queue_node sem_queue_node; }; +#pragma pack(pop) + +struct kernel_version { + unsigned int kernel_version; + unsigned int major_version; + unsigned int minor_version; + unsigned int build_number; +}; + +int get_kernel_version(struct kernel_version *version); struct thread_context *thread_create( struct thread_context *thread, @@ -45,6 +57,7 @@ struct thread_context *thread_create( void *arg, enum thread_priority priority); + void thread_exit(void); void sleep_ms(unsigned int ms); diff --git a/source/os/release/include/list.h b/source/os/release/include/list.h new file mode 100644 index 0000000..f26b4fe --- /dev/null +++ b/source/os/release/include/list.h @@ -0,0 +1,25 @@ +/* + * list.h + * + * Created on: Jul 27, 2016 + * Author: tkl + */ + +#ifndef SOURCE_FIRMWARE_KERNEL_LIST_H_ +#define SOURCE_FIRMWARE_KERNEL_LIST_H_ + +struct list_node { + struct list_node *next; + unsigned int data; +}; + +struct list { + struct list_node *front; + struct list_node *rear; +}; + +int list_init(struct list *head); +int list_add(struct list *head, struct list_node *node); +int list_get_len(struct list *head); + +#endif /* SOURCE_FIRMWARE_KERNEL_LIST_H_ */ diff --git a/source/os/release/include/shell.h b/source/os/release/include/shell.h new file mode 100644 index 0000000..c242e8d --- /dev/null +++ b/source/os/release/include/shell.h @@ -0,0 +1,23 @@ +/* + * 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 char *description; + 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/os/release/libkosmos-arm-stm32f4-discovery-0.1.4.a b/source/os/release/libkosmos-arm-stm32f4-discovery-0.1.4.a new file mode 100644 index 0000000..ec2ac10 Binary files /dev/null and b/source/os/release/libkosmos-arm-stm32f4-discovery-0.1.4.a differ diff --git a/source/os/release/libkosmos-arm-stm32f4-discovery.a b/source/os/release/libkosmos-arm-stm32f4-discovery.a deleted file mode 100644 index 8455371..0000000 Binary files a/source/os/release/libkosmos-arm-stm32f4-discovery.a and /dev/null differ diff --git a/source/os/release/libkosmos-arm-stm32f4-discovery.a b/source/os/release/libkosmos-arm-stm32f4-discovery.a new file mode 120000 index 0000000..b1368da --- /dev/null +++ b/source/os/release/libkosmos-arm-stm32f4-discovery.a @@ -0,0 +1 @@ +libkosmos-arm-stm32f4-discovery-0.1.4.a \ No newline at end of file diff --git a/source/scripts/release_number.py b/source/scripts/release_number.py new file mode 100755 index 0000000..af01f6f --- /dev/null +++ b/source/scripts/release_number.py @@ -0,0 +1,43 @@ +#!/usr/bin/python2 +from sys import argv, exit +from getopt import getopt +from re import match, sub +import os + +def get_current_numbers(): + config = {} + if os.environ.has_key("SW_MAJOR"): + config["sw_major"] = os.environ["SW_MAJOR"] + if os.environ.has_key("SW_MINOR"): + config["sw_minor"] = os.environ["SW_MINOR"] + if os.environ.has_key("CI_BUILD_ID"): + config["build_id"] = os.environ["CI_BUILD_ID"] + return config + +def generate_include(numbers): + f = open("source/application/include/version.h", "w") + f.write("/* Release number include file */\n\n") + f.write("#ifndef VERSION_H\n") + f.write("#define VERSION_H\n\n") + if numbers.has_key("sw_major"): + f.write("#define MAJOR_VERSION\t\"" + numbers["sw_major"] + "\"\n") + else: + f.write("#define MAJOR_VERSION\t\"unknown\"\n") + if numbers.has_key("sw_minor"): + f.write("#define MINOR_VERSION\t\"" + numbers["sw_minor"] + "\"\n") + else: + f.write("#define MINOR_VERSION\t\"unknown\"\n") + if numbers.has_key("build_id"): + f.write("#define BUILD_NUMBER\t\"" + numbers["build_id"] + "\"\n") + else: + f.write("#define BUILD_NUMBER\t\"unknown\"\n") + f.write("\n#endif /* VERSION_H */\n") + f.close() + +def main(argv): + numbers = get_current_numbers() + generate_include(numbers) + +if __name__ == "__main__": + main(argv[1:]) + diff --git a/source/system/stm32f4xx/ExceptionHandlers.h b/source/system/stm32f4xx/ExceptionHandlers.h new file mode 100644 index 0000000..b69b8eb --- /dev/null +++ b/source/system/stm32f4xx/ExceptionHandlers.h @@ -0,0 +1,94 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +#ifndef CORTEXM_EXCEPTION_HANDLERS_H_ +#define CORTEXM_EXCEPTION_HANDLERS_H_ + +#include + +#if defined(DEBUG) +#define __DEBUG_BKPT() asm volatile ("bkpt 0") +#endif + +// ---------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// External references to cortexm_handlers.c + + extern void + Reset_Handler (void); + extern void + NMI_Handler (void); + extern void + HardFault_Handler (void); + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + extern void + MemManage_Handler (void); + extern void + BusFault_Handler (void); + extern void + UsageFault_Handler (void); + extern void + DebugMon_Handler (void); +#endif + + extern void + SVC_Handler (void); + + extern void + PendSV_Handler (void); + extern void + SysTick_Handler (void); + + // Exception Stack Frame of the Cortex-M3 or Cortex-M4 processor. + typedef struct + { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t psr; +#if defined(__ARM_ARCH_7EM__) + uint32_t s[16]; +#endif + } ExceptionStackFrame; + +#if defined(TRACE) +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + void + dumpExceptionStack (ExceptionStackFrame* frame, uint32_t cfsr, uint32_t mmfar, + uint32_t bfar, uint32_t lr); +#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) +#if defined(__ARM_ARCH_6M__) + void + dumpExceptionStack (ExceptionStackFrame* frame, uint32_t lr); +#endif // defined(__ARM_ARCH_6M__) +#endif // defined(TRACE) + + void + HardFault_Handler_C (ExceptionStackFrame* frame, uint32_t lr); + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + void + UsageFault_Handler_C (ExceptionStackFrame* frame, uint32_t lr); + void + BusFault_Handler_C (ExceptionStackFrame* frame, uint32_t lr); +#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +#if defined(__cplusplus) +} +#endif + +// ---------------------------------------------------------------------------- + +#endif // CORTEXM_EXCEPTION_HANDLERS_H_ diff --git a/source/system/stm32f4xx/_cxx.cpp b/source/system/stm32f4xx/_cxx.cpp new file mode 100644 index 0000000..efcb451 --- /dev/null +++ b/source/system/stm32f4xx/_cxx.cpp @@ -0,0 +1,50 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +// These functions are redefined locally, to avoid references to some +// heavy implementations in the standard C++ library. + +// ---------------------------------------------------------------------------- + +#include +#include +#include "diag/Trace.h" + +// ---------------------------------------------------------------------------- + +namespace __gnu_cxx +{ + void + __attribute__((noreturn)) + __verbose_terminate_handler(); + + void + __verbose_terminate_handler() + { + trace_puts(__func__); + abort(); + } +} + +// ---------------------------------------------------------------------------- + +extern "C" +{ + void + __attribute__((noreturn)) + __cxa_pure_virtual(); + + void + __cxa_pure_virtual() + { + trace_puts(__func__); + abort(); + } +} + +// ---------------------------------------------------------------------------- + diff --git a/source/system/stm32f4xx/_exit.c b/source/system/stm32f4xx/_exit.c new file mode 100644 index 0000000..fb1d71a --- /dev/null +++ b/source/system/stm32f4xx/_exit.c @@ -0,0 +1,59 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +#include +//#include "diag/Trace.h" + +// ---------------------------------------------------------------------------- + +#if !defined(DEBUG) +extern void +__attribute__((noreturn)) +__reset_hardware(void); +#endif + +// ---------------------------------------------------------------------------- + +// Forward declaration + +void +_exit(int code); + +// ---------------------------------------------------------------------------- + +// On Release, call the hardware reset procedure. +// On Debug we just enter an infinite loop, to be used as landmark when halting +// the debugger. +// +// It can be redefined in the application, if more functionality +// is required. + +void +__attribute__((weak)) +_exit(int code __attribute__((unused))) +{ +#if !defined(DEBUG) + __reset_hardware(); +#endif + + // TODO: write on trace + while (1) + ; +} + +// ---------------------------------------------------------------------------- + +void +__attribute__((weak,noreturn)) +abort(void) +{ +// trace_puts("abort(), exiting..."); + while(1); + _exit(1); +} + +// ---------------------------------------------------------------------------- diff --git a/source/system/stm32f4xx/_sbrk.c b/source/system/stm32f4xx/_sbrk.c new file mode 100644 index 0000000..ac3a8aa --- /dev/null +++ b/source/system/stm32f4xx/_sbrk.c @@ -0,0 +1,65 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +#include +#include + +// ---------------------------------------------------------------------------- + +caddr_t +_sbrk(int incr); + +// ---------------------------------------------------------------------------- + +// The definitions used here should be kept in sync with the +// stack definitions in the linker script. + +caddr_t +_sbrk(int incr) +{ + extern char _Heap_Begin; // Defined by the linker. + extern char _Heap_Limit; // Defined by the linker. + + static char* current_heap_end; + char* current_block_address; + + if (current_heap_end == 0) + { + current_heap_end = &_Heap_Begin; + } + + current_block_address = current_heap_end; + + // Need to align heap to word boundary, else will get + // hard faults on Cortex-M0. So we assume that heap starts on + // word boundary, hence make sure we always add a multiple of + // 4 to it. + incr = (incr + 3) & (~3); // align value to 4 + if (current_heap_end + incr > &_Heap_Limit) + { + // Some of the libstdc++-v3 tests rely upon detecting + // out of memory errors, so do not abort here. +#if 0 + extern void abort (void); + + _write (1, "_sbrk: Heap and stack collision\n", 32); + + abort (); +#else + // Heap has overflowed + errno = ENOMEM; + return (caddr_t) - 1; +#endif + } + + current_heap_end += incr; + + return (caddr_t) current_block_address; +} + +// ---------------------------------------------------------------------------- + diff --git a/source/system/stm32f4xx/_startup.c b/source/system/stm32f4xx/_startup.c new file mode 100644 index 0000000..169538c --- /dev/null +++ b/source/system/stm32f4xx/_startup.c @@ -0,0 +1,327 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +// This module contains the startup code for a portable embedded +// C/C++ application, built with newlib. +// +// Control reaches here from the reset handler via jump or call. +// +// The actual steps performed by _start are: +// - copy the initialised data region(s) +// - clear the BSS region(s) +// - initialise the system +// - run the preinit/init array (for the C++ static constructors) +// - initialise the arc/argv +// - branch to main() +// - run the fini array (for the C++ static destructors) +// - call _exit(), directly or via exit() +// +// If OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS is defined, the +// code is capable of initialising multiple regions. +// +// The normal configuration is standalone, with all support +// functions implemented locally. +// +// For this to be called, the project linker must be configured without +// the startup sequence (-nostartfiles). + +// ---------------------------------------------------------------------------- + +#include +#include + +// ---------------------------------------------------------------------------- + +#if !defined(OS_INCLUDE_STARTUP_GUARD_CHECKS) +#define OS_INCLUDE_STARTUP_GUARD_CHECKS (1) +#endif + +// ---------------------------------------------------------------------------- + +#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS) +// Begin address for the initialisation values of the .data section. +// defined in linker script +extern unsigned int _sidata; +// Begin address for the .data section; defined in linker script +extern unsigned int _sdata; +// End address for the .data section; defined in linker script +extern unsigned int _edata; + +// Begin address for the .bss section; defined in linker script +extern unsigned int __bss_start__; +// End address for the .bss section; defined in linker script +extern unsigned int __bss_end__; +#else +// The following symbols are constructs generated by the linker, indicating +// the location of various points in the "Memory regions initialisation arrays". +// These arrays are created by the linker via the managed linker script +// of each RW data mechanism. It contains the load address, execution address +// and length section and the execution and length of each BSS (zero +// initialised) section. +extern unsigned int __data_regions_array_start; +extern unsigned int __data_regions_array_end; +extern unsigned int __bss_regions_array_start; +extern unsigned int __bss_regions_array_end; +#endif + +extern void +__initialize_args (int*, char***); + +// main() is the entry point for newlib based applications. +// By default, there are no arguments, but this can be customised +// by redefining __initialize_args(), which is done when the +// semihosting configurations are used. +extern int +start_application (int argc, char* argv[]); + +// The implementation for the exit routine; for embedded +// applications, a system reset will be performed. +extern void +__attribute__((noreturn)) +_exit (int); + +// ---------------------------------------------------------------------------- + +// Forward declarations + +void +_start (void); + +void +__initialize_data (unsigned int* from, unsigned int* region_begin, + unsigned int* region_end); + +void +__initialize_bss (unsigned int* region_begin, unsigned int* region_end); + +void +__run_init_array (void); + +void +__run_fini_array (void); + +void +__initialize_hardware_early (void); + +void +__initialize_hardware (void); + +// ---------------------------------------------------------------------------- + +inline void +__attribute__((always_inline)) +__initialize_data (unsigned int* from, unsigned int* region_begin, + unsigned int* region_end) +{ + // Iterate and copy word by word. + // It is assumed that the pointers are word aligned. + unsigned int *p = region_begin; + while (p < region_end) + *p++ = *from++; +} + +inline void +__attribute__((always_inline)) +__initialize_bss (unsigned int* region_begin, unsigned int* region_end) +{ + // Iterate and clear word by word. + // It is assumed that the pointers are word aligned. + unsigned int *p = region_begin; + while (p < region_end) + *p++ = 0; +} + +// These magic symbols are provided by the linker. +extern void +(*__preinit_array_start[]) (void) __attribute__((weak)); +extern void +(*__preinit_array_end[]) (void) __attribute__((weak)); +extern void +(*__init_array_start[]) (void) __attribute__((weak)); +extern void +(*__init_array_end[]) (void) __attribute__((weak)); +extern void +(*__fini_array_start[]) (void) __attribute__((weak)); +extern void +(*__fini_array_end[]) (void) __attribute__((weak)); + +// Iterate over all the preinit/init routines (mainly static constructors). +inline void +__attribute__((always_inline)) +__run_init_array (void) +{ + int count; + int i; + + count = __preinit_array_end - __preinit_array_start; + for (i = 0; i < count; i++) + __preinit_array_start[i] (); + + // If you need to run the code in the .init section, please use + // the startup files, since this requires the code in crti.o and crtn.o + // to add the function prologue/epilogue. + //_init(); // DO NOT ENABE THIS! + + count = __init_array_end - __init_array_start; + for (i = 0; i < count; i++) + __init_array_start[i] (); +} + +// Run all the cleanup routines (mainly static destructors). +inline void +__attribute__((always_inline)) +__run_fini_array (void) +{ + int count; + int i; + + count = __fini_array_end - __fini_array_start; + for (i = count; i > 0; i--) + __fini_array_start[i - 1] (); + + // If you need to run the code in the .fini section, please use + // the startup files, since this requires the code in crti.o and crtn.o + // to add the function prologue/epilogue. + //_fini(); // DO NOT ENABE THIS! +} + +#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + +// These definitions are used to check if the routines used to +// clear the BSS and to copy the initialised DATA perform correctly. + +#define BSS_GUARD_BAD_VALUE (0xCADEBABA) + +static uint32_t volatile __attribute__ ((section(".bss_begin"))) +__bss_begin_guard; +static uint32_t volatile __attribute__ ((section(".bss_end"))) +__bss_end_guard; + +#define DATA_GUARD_BAD_VALUE (0xCADEBABA) +#define DATA_BEGIN_GUARD_VALUE (0x12345678) +#define DATA_END_GUARD_VALUE (0x98765432) + +static uint32_t volatile __attribute__ ((section(".data_begin"))) +__data_begin_guard = DATA_BEGIN_GUARD_VALUE; + +static uint32_t volatile __attribute__ ((section(".data_end"))) +__data_end_guard = DATA_END_GUARD_VALUE; + +#endif // defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + +// This is the place where Cortex-M core will go immediately after reset, +// via a call or jump from the Reset_Handler. +// +// For the call to work, and for the call to __initialize_hardware_early() +// to work, the reset stack must point to a valid internal RAM area. + +void __attribute__ ((section(".after_vectors"),noreturn,weak)) +_start (void) +{ + + // Initialise hardware right after reset, to switch clock to higher + // frequency and have the rest of the initialisations run faster. + // + // Mandatory on platforms like Kinetis, which start with the watch dog + // enabled and require an early sequence to disable it. + // + // Also useful on platform with external RAM, that need to be + // initialised before filling the BSS section. + + __initialize_hardware_early (); + + // Use Old Style DATA and BSS section initialisation, + // that will manage a single BSS sections. + +#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + __data_begin_guard = DATA_GUARD_BAD_VALUE; + __data_end_guard = DATA_GUARD_BAD_VALUE; +#endif + +#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS) + // Copy the DATA segment from Flash to RAM (inlined). + __initialize_data(&_sidata, &_sdata, &_edata); +#else + + // Copy the data sections from flash to SRAM. + for (unsigned int* p = &__data_regions_array_start; + p < &__data_regions_array_end;) + { + unsigned int* from = (unsigned int *) (*p++); + unsigned int* region_begin = (unsigned int *) (*p++); + unsigned int* region_end = (unsigned int *) (*p++); + + __initialize_data (from, region_begin, region_end); + } + +#endif + +#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + if ((__data_begin_guard != DATA_BEGIN_GUARD_VALUE) + || (__data_end_guard != DATA_END_GUARD_VALUE)) + { + for (;;) + ; + } +#endif + +#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + __bss_begin_guard = BSS_GUARD_BAD_VALUE; + __bss_end_guard = BSS_GUARD_BAD_VALUE; +#endif + +#if !defined(OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS) + // Zero fill the BSS section (inlined). + __initialize_bss(&__bss_start__, &__bss_end__); +#else + + // Zero fill all bss segments + for (unsigned int *p = &__bss_regions_array_start; + p < &__bss_regions_array_end;) + { + unsigned int* region_begin = (unsigned int*) (*p++); + unsigned int* region_end = (unsigned int*) (*p++); + __initialize_bss (region_begin, region_end); + } +#endif + +#if defined(DEBUG) && (OS_INCLUDE_STARTUP_GUARD_CHECKS) + if ((__bss_begin_guard != 0) || (__bss_end_guard != 0)) + { + for (;;) + ; + } +#endif + + // Hook to continue the initialisations. Usually compute and store the + // clock frequency in the global CMSIS variable, cleared above. + __initialize_hardware (); + + // Get the argc/argv (useful in semihosting configurations). + int argc; + char** argv; + __initialize_args (&argc, &argv); + + // Call the standard library initialisation (mandatory for C++ to + // execute the constructors for the static objects). + __run_init_array (); + + // Call the main entry point, and save the exit code. + int code = start_application (argc, argv); + + // Run the C++ static destructors. + __run_fini_array (); + + _exit (code); + + // Should never reach this, _exit() should have already + // performed a reset. + for (;;) + ; +} + +// ---------------------------------------------------------------------------- diff --git a/source/system/stm32f4xx/_syscalls.c b/source/system/stm32f4xx/_syscalls.c new file mode 100644 index 0000000..3e930c5 --- /dev/null +++ b/source/system/stm32f4xx/_syscalls.c @@ -0,0 +1,1219 @@ +// +// This file is part of the µOS++ III distribution. +// Parts of this file are from the newlib sources, issued under GPL. +// Copyright (c) 2014 Liviu Ionescu +// + +// ---------------------------------------------------------------------------- + +int errno; +void *__dso_handle __attribute__ ((weak)); + +// ---------------------------------------------------------------------------- + +#if !defined(OS_USE_SEMIHOSTING) + +#include <_ansi.h> +#include <_syslist.h> +#include +//#include +#include +#include +#include +#include +#include + +void +__initialize_args(int* p_argc, char*** p_argv); + +// This is the standard default implementation for the routine to +// process args. It returns a single empty arg. +// For semihosting applications, this is redefined to get the real +// args from the debugger. You can also use it if you decide to keep +// some args in a non-volatile memory. + +void __attribute__((weak)) +__initialize_args(int* p_argc, char*** p_argv) +{ + // By the time we reach this, the data and bss should have been initialised. + + // The strings pointed to by the argv array shall be modifiable by the + // program, and retain their last-stored values between program startup + // and program termination. (static, no const) + static char name[] = ""; + + // The string pointed to by argv[0] represents the program name; + // argv[0][0] shall be the null character if the program name is not + // available from the host environment. argv[argc] shall be a null pointer. + // (static, no const) + static char* argv[2] = + { name, NULL }; + + *p_argc = 1; + *p_argv = &argv[0]; + return; +} + +// These functions are defined here to avoid linker errors in freestanding +// applications. They might be called in some error cases from library +// code. +// +// If you detect other functions to be needed, just let us know +// and we'll add them. + +int +raise(int sig __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int +kill(pid_t pid, int sig); + +int +kill(pid_t pid __attribute__((unused)), int sig __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +#endif // !defined(OS_USE_SEMIHOSTING) + +// ---------------------------------------------------------------------------- + +// If you need the empty definitions, remove the -ffreestanding option. + +#if __STDC_HOSTED__ == 1 + +char* __env[1] = + { 0 }; +char** environ = __env; + +#if !defined(OS_USE_SEMIHOSTING) + +// Forward declarations + +int +_chown(const char* path, uid_t owner, gid_t group); + +int +_close(int fildes); + +int +_execve(char* name, char** argv, char** env); + +int +_fork(void); + +int +_fstat(int fildes, struct stat* st); + +int +_getpid(void); + +int +_gettimeofday(struct timeval* ptimeval, void* ptimezone); + +int +_isatty(int file); + +int +_kill(int pid, int sig); + +int +_link(char* existing, char* _new); + +int +_lseek(int file, int ptr, int dir); + +int +_open(char* file, int flags, int mode); + +int +_read(int file, char* ptr, int len); + +int +_readlink(const char* path, char* buf, size_t bufsize); + +int +_stat(const char* file, struct stat* st); + +int +_symlink(const char* path1, const char* path2); + +clock_t +_times(struct tms* buf); + +int +_unlink(char* name); + +int +_wait(int* status); + +int +_write(int file, char* ptr, int len); + +// Definitions + +int __attribute__((weak)) +_chown(const char* path __attribute__((unused)), + uid_t owner __attribute__((unused)), gid_t group __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_close(int fildes __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_execve(char* name __attribute__((unused)), char** argv __attribute__((unused)), + char** env __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_fork(void) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_fstat(int fildes __attribute__((unused)), + struct stat* st __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_getpid(void) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_gettimeofday(struct timeval* ptimeval __attribute__((unused)), + void* ptimezone __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_isatty(int file __attribute__((unused))) +{ + errno = ENOSYS; + return 0; +} + +int __attribute__((weak)) +_kill(int pid __attribute__((unused)), int sig __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_link(char* existing __attribute__((unused)), + char* _new __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_lseek(int file __attribute__((unused)), int ptr __attribute__((unused)), + int dir __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_open(char* file __attribute__((unused)), int flags __attribute__((unused)), + int mode __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_read(int file __attribute__((unused)), char* ptr __attribute__((unused)), + int len __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_readlink(const char* path __attribute__((unused)), + char* buf __attribute__((unused)), size_t bufsize __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_stat(const char* file __attribute__((unused)), + struct stat* st __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_symlink(const char* path1 __attribute__((unused)), + const char* path2 __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +clock_t __attribute__((weak)) +_times(struct tms* buf __attribute__((unused))) +{ + errno = ENOSYS; + return ((clock_t) -1); +} + +int __attribute__((weak)) +_unlink(char* name __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_wait(int* status __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +int __attribute__((weak)) +_write(int file __attribute__((unused)), char* ptr __attribute__((unused)), + int len __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +// ---------------------------------------------------------------------------- + +#else // defined(OS_USE_SEMIHOSTING) + +// ---------------------------------------------------------------------------- + +/* Support files for GNU libc. Files in the system namespace go here. + Files in the C namespace (ie those that do not start with an + underscore) go in .c. */ + +#include <_ansi.h> +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arm/semihosting.h" + +int +_kill (int pid, int sig); + +void +__attribute__((noreturn)) +_exit (int status); + +// Forward declarations. +int +_system (const char*); +int +_rename (const char*, const char*); +int +_isatty (int); +clock_t +_times (struct tms*); +int +_gettimeofday (struct timeval *, void*); +int +_unlink (const char*); +int +_link (void); + +int +_stat (const char*, struct stat*); + +int +_fstat (int, struct stat*); +int +_swistat (int fd, struct stat* st); +int +_getpid (int); +int +_close (int); +clock_t +_clock (void); +int +_swiclose (int); +int +_open (const char*, int, ...); +int +_swiopen (const char*, int); +int +_write (int, char*, int); +int +_swiwrite (int, char*, int); +int +_lseek (int, int, int); +int +_swilseek (int, int, int); +int +_read (int, char*, int); +int +_swiread (int, char*, int); + +void +initialise_monitor_handles (void); + +void +__initialize_args (int* p_argc, char*** p_argv); + +static int +checkerror (int); +static int +error (int); +static int +get_errno (void); + +// ---------------------------------------------------------------------------- + +#define ARGS_BUF_ARRAY_SIZE 80 +#define ARGV_BUF_ARRAY_SIZE 10 + +typedef struct +{ + char* pCommandLine; + int size; +} CommandLineBlock; + +void +__initialize_args (int* p_argc, char*** p_argv) +{ + + // Array of chars to receive the command line from the host + static char args_buf[ARGS_BUF_ARRAY_SIZE]; + + // Array of pointers to store the final argv pointers (pointing + // in the above array). + static char* argv_buf[ARGV_BUF_ARRAY_SIZE]; + + int argc = 0; + int isInArgument = 0; + + CommandLineBlock cmdBlock; + cmdBlock.pCommandLine = args_buf; + cmdBlock.size = sizeof(args_buf) - 1; + + int ret = call_host (SEMIHOSTING_SYS_GET_CMDLINE, &cmdBlock); + if (ret == 0) + { + + // In case the host send more than we can chew, limit the + // string to our buffer. + args_buf[ARGS_BUF_ARRAY_SIZE - 1] = '\0'; + + // The command line is a null terminated string + char* p = cmdBlock.pCommandLine; + + int delim = '\0'; + int ch; + + while ((ch = *p) != '\0') + { + if (isInArgument == 0) + { + if (!isblank(ch)) + { + if (argc + >= (int) ((sizeof(argv_buf) / sizeof(argv_buf[0])) - 1)) + break; + + if (ch == '"' || ch == '\'') + { + // Remember the delimiter to search for the + // corresponding terminator + delim = ch; + ++p; // skip the delimiter + ch = *p; + } + // Remember the arg beginning address + argv_buf[argc++] = p; + isInArgument = 1; + } + } + else if (delim != '\0') + { + if ((ch == delim)) + { + delim = '\0'; + *p = '\0'; + isInArgument = 0; + } + } + else if (isblank(ch)) + { + delim = '\0'; + *p = '\0'; + isInArgument = 0; + } + ++p; + } + } + + if (argc == 0) + { + // No args found in string, return a single empty name. + args_buf[0] = '\0'; + argv_buf[0] = &args_buf[0]; + ++argc; + } + + // Must end the array with a null pointer. + argv_buf[argc] = NULL; + + *p_argc = argc; + *p_argv = &argv_buf[0]; + + // temporary here + initialise_monitor_handles (); + + return; +} + +// ---------------------------------------------------------------------------- + +void +_exit (int status) +{ + /* There is only one SWI for both _exit and _kill. For _exit, call + the SWI with the second argument set to -1, an invalid value for + signum, so that the SWI handler can distinguish the two calls. + Note: The RDI implementation of _kill throws away both its + arguments. */ + report_exception ( + status == 0 ? ADP_Stopped_ApplicationExit : ADP_Stopped_RunTimeError); +} + +// ---------------------------------------------------------------------------- + +int __attribute__((weak)) +_kill (int pid __attribute__((unused)), int sig __attribute__((unused))) +{ + errno = ENOSYS; + return -1; +} + +// ---------------------------------------------------------------------------- + +/* Struct used to keep track of the file position, just so we + can implement fseek(fh,x,SEEK_CUR). */ +struct fdent +{ + int handle; + int pos; +}; + +#define MAX_OPEN_FILES 20 + +/* User file descriptors (fd) are integer indexes into + the openfiles[] array. Error checking is done by using + findslot(). + + This openfiles array is manipulated directly by only + these 5 functions: + + findslot() - Translate entry. + newslot() - Find empty entry. + initilise_monitor_handles() - Initialize entries. + _swiopen() - Initialize entry. + _close() - Handle stdout == stderr case. + + Every other function must use findslot(). */ + +static struct fdent openfiles[MAX_OPEN_FILES]; + +static struct fdent* +findslot (int); +static int +newslot (void); + +/* Register name faking - works in collusion with the linker. */ +register char* stack_ptr asm ("sp"); + +/* following is copied from libc/stdio/local.h to check std streams */ +extern void _EXFUN(__sinit,(struct _reent*)); +#define CHECK_INIT(ptr) \ + do \ + { \ + if ((ptr) && !(ptr)->__sdidinit) \ + __sinit (ptr); \ + } \ + while (0) + +static int monitor_stdin; +static int monitor_stdout; +static int monitor_stderr; + +/* Return a pointer to the structure associated with + the user file descriptor fd. */ +static struct fdent* +findslot (int fd) +{ + CHECK_INIT(_REENT); + + /* User file descriptor is out of range. */ + if ((unsigned int) fd >= MAX_OPEN_FILES) + { + return NULL; + } + + /* User file descriptor is open? */ + if (openfiles[fd].handle == -1) + { + return NULL; + } + + /* Valid. */ + return &openfiles[fd]; +} + +/* Return the next lowest numbered free file + structure, or -1 if we can't find one. */ +static int +newslot (void) +{ + int i; + + for (i = 0; i < MAX_OPEN_FILES; i++) + { + if (openfiles[i].handle == -1) + { + break; + } + } + + if (i == MAX_OPEN_FILES) + { + return -1; + } + + return i; +} + +void +initialise_monitor_handles (void) +{ + int i; + + /* Open the standard file descriptors by opening the special + * teletype device, ":tt", read-only to obtain a descriptor for + * standard input and write-only to obtain a descriptor for standard + * output. Finally, open ":tt" in append mode to obtain a descriptor + * for standard error. Since this is a write mode, most kernels will + * probably return the same value as for standard output, but the + * kernel can differentiate the two using the mode flag and return a + * different descriptor for standard error. + */ + + int volatile block[3]; + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 0; /* mode "r" */ + monitor_stdin = call_host (SEMIHOSTING_SYS_OPEN, (void*) block); + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 4; /* mode "w" */ + monitor_stdout = call_host (SEMIHOSTING_SYS_OPEN, (void*) block); + + block[0] = (int) ":tt"; + block[2] = 3; /* length of filename */ + block[1] = 8; /* mode "a" */ + monitor_stderr = call_host (SEMIHOSTING_SYS_OPEN, (void*) block); + + /* If we failed to open stderr, redirect to stdout. */ + if (monitor_stderr == -1) + { + monitor_stderr = monitor_stdout; + } + + for (i = 0; i < MAX_OPEN_FILES; i++) + { + openfiles[i].handle = -1; + } + + openfiles[0].handle = monitor_stdin; + openfiles[0].pos = 0; + openfiles[1].handle = monitor_stdout; + openfiles[1].pos = 0; + openfiles[2].handle = monitor_stderr; + openfiles[2].pos = 0; +} + +static int +get_errno (void) +{ + return call_host (SEMIHOSTING_SYS_ERRNO, NULL); +} + +/* Set errno and return result. */ +static int +error (int result) +{ + errno = get_errno (); + return result; +} + +/* Check the return and set errno appropriately. */ +static int +checkerror (int result) +{ + if (result == -1) + { + return error (-1); + } + + return result; +} + +/* fh, is a valid internal file handle. + ptr, is a null terminated string. + len, is the length in bytes to read. + Returns the number of bytes *not* written. */ +int +_swiread (int fh, char* ptr, int len) +{ + int block[3]; + + block[0] = fh; + block[1] = (int) ptr; + block[2] = len; + + return checkerror (call_host (SEMIHOSTING_SYS_READ, block)); +} + +/* fd, is a valid user file handle. + Translates the return of _swiread into + bytes read. */ +int +_read (int fd, char* ptr, int len) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + res = _swiread (pfd->handle, ptr, len); + + if (res == -1) + { + return res; + } + + pfd->pos += len - res; + + /* res == len is not an error, + at least if we want feof() to work. */ + return len - res; +} + +/* fd, is a user file descriptor. */ +int +_swilseek (int fd, int ptr, int dir) +{ + int res; + struct fdent *pfd; + + /* Valid file descriptor? */ + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Valid whence? */ + if ((dir != SEEK_CUR) && (dir != SEEK_SET) && (dir != SEEK_END)) + { + errno = EINVAL; + return -1; + } + + /* Convert SEEK_CUR to SEEK_SET */ + if (dir == SEEK_CUR) + { + ptr = pfd->pos + ptr; + /* The resulting file offset would be negative. */ + if (ptr < 0) + { + errno = EINVAL; + if ((pfd->pos > 0) && (ptr > 0)) + { + errno = EOVERFLOW; + } + return -1; + } + dir = SEEK_SET; + } + + int block[2]; + if (dir == SEEK_END) + { + block[0] = pfd->handle; + res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, block)); + if (res == -1) + { + return -1; + } + ptr += res; + } + + /* This code only does absolute seeks. */ + block[0] = pfd->handle; + block[1] = ptr; + res = checkerror (call_host (SEMIHOSTING_SYS_SEEK, block)); + + /* At this point ptr is the current file position. */ + if (res >= 0) + { + pfd->pos = ptr; + return ptr; + } + else + { + return -1; + } +} + +int +_lseek (int fd, int ptr, int dir) +{ + return _swilseek (fd, ptr, dir); +} + +/* fh, is a valid internal file handle. + Returns the number of bytes *not* written. */ +int +_swiwrite (int fh, char* ptr, int len) +{ + int block[3]; + + block[0] = fh; + block[1] = (int) ptr; + block[2] = len; + + return checkerror (call_host (SEMIHOSTING_SYS_WRITE, block)); +} + +/* fd, is a user file descriptor. */ +int +_write (int fd, char* ptr, int len) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + res = _swiwrite (pfd->handle, ptr, len); + + /* Clearly an error. */ + if (res < 0) + { + return -1; + } + + pfd->pos += len - res; + + /* We wrote 0 bytes? + Retrieve errno just in case. */ + if ((len - res) == 0) + { + return error (0); + } + + return (len - res); +} + +int +_swiopen (const char* path, int flags) +{ + int aflags = 0, fh; + uint32_t block[3]; + + int fd = newslot (); + + if (fd == -1) + { + errno = EMFILE; + return -1; + } + + /* It is an error to open a file that already exists. */ + if ((flags & O_CREAT) && (flags & O_EXCL)) + { + struct stat st; + int res; + res = _stat (path, &st); + if (res != -1) + { + errno = EEXIST; + return -1; + } + } + + /* The flags are Unix-style, so we need to convert them. */ +#ifdef O_BINARY + if (flags & O_BINARY) + { + aflags |= 1; + } +#endif + + /* In O_RDONLY we expect aflags == 0. */ + + if (flags & O_RDWR) + { + aflags |= 2; + } + + if ((flags & O_CREAT) || (flags & O_TRUNC) || (flags & O_WRONLY)) + { + aflags |= 4; + } + + if (flags & O_APPEND) + { + /* Can't ask for w AND a; means just 'a'. */ + aflags &= ~4; + aflags |= 8; + } + + block[0] = (uint32_t) path; + block[2] = strlen (path); + block[1] = (uint32_t) aflags; + + fh = call_host (SEMIHOSTING_SYS_OPEN, block); + + /* Return a user file descriptor or an error. */ + if (fh >= 0) + { + openfiles[fd].handle = fh; + openfiles[fd].pos = 0; + return fd; + } + else + { + return error (fh); + } +} + +int +_open (const char* path, int flags, ...) +{ + return _swiopen (path, flags); +} + +/* fh, is a valid internal file handle. */ +int +_swiclose (int fh) +{ + return checkerror (call_host (SEMIHOSTING_SYS_CLOSE, &fh)); +} + +/* fd, is a user file descriptor. */ +int +_close (int fd) +{ + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Handle stderr == stdout. */ + if ((fd == 1 || fd == 2) && (openfiles[1].handle == openfiles[2].handle)) + { + pfd->handle = -1; + return 0; + } + + /* Attempt to close the handle. */ + res = _swiclose (pfd->handle); + + /* Reclaim handle? */ + if (res == 0) + { + pfd->handle = -1; + } + + return res; +} + +int __attribute__((weak)) +_getpid (int n __attribute__ ((unused))) +{ + return 1; +} + +int +_swistat (int fd, struct stat* st) +{ + struct fdent *pfd; + int res; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Always assume a character device, + with 1024 byte blocks. */ + st->st_mode |= S_IFCHR; + st->st_blksize = 1024; + res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, &pfd->handle)); + if (res == -1) + { + return -1; + } + + /* Return the file size. */ + st->st_size = res; + return 0; +} + +int __attribute__((weak)) +_fstat (int fd, struct stat* st) +{ + memset (st, 0, sizeof(*st)); + return _swistat (fd, st); +} + +int __attribute__((weak)) +_stat (const char*fname, struct stat *st) +{ + int fd, res; + memset (st, 0, sizeof(*st)); + /* The best we can do is try to open the file readonly. + If it exists, then we can guess a few things about it. */ + if ((fd = _open (fname, O_RDONLY)) == -1) + { + return -1; + } + st->st_mode |= S_IFREG | S_IREAD; + res = _swistat (fd, st); + /* Not interested in the error. */ + _close (fd); + return res; +} + +int __attribute__((weak)) +_link (void) +{ + errno = ENOSYS; + return -1; +} + +int +_unlink (const char* path) +{ + int res; + uint32_t block[2]; + block[0] = (uint32_t) path; + block[1] = strlen (path); + res = call_host (SEMIHOSTING_SYS_REMOVE, block); + + if (res == -1) + { + return error (res); + } + return 0; +} + +int +_gettimeofday (struct timeval* tp, void* tzvp) +{ + struct timezone* tzp = tzvp; + if (tp) + { + /* Ask the host for the seconds since the Unix epoch. */ + tp->tv_sec = call_host (SEMIHOSTING_SYS_TIME, NULL); + tp->tv_usec = 0; + } + + /* Return fixed data for the timezone. */ + if (tzp) + { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + + return 0; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t +_clock (void) +{ + clock_t timeval; + + timeval = (clock_t) call_host (SEMIHOSTING_SYS_CLOCK, NULL); + return timeval; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t +_times (struct tms* tp) +{ + clock_t timeval = _clock (); + + if (tp) + { + tp->tms_utime = timeval; /* user time */ + tp->tms_stime = 0; /* system time */ + tp->tms_cutime = 0; /* user time, children */ + tp->tms_cstime = 0; /* system time, children */ + } + + return timeval; +} + +int +_isatty (int fd) +{ + struct fdent *pfd; + int tty; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return 0; + } + + tty = call_host (SEMIHOSTING_SYS_ISTTY, &pfd->handle); + + if (tty == 1) + { + return 1; + } + + errno = get_errno (); + return 0; +} + +int +_system (const char* s) +{ + uint32_t block[2]; + int e; + + /* Hmmm. The ARM debug interface specification doesn't say whether + SYS_SYSTEM does the right thing with a null argument, or assign any + meaning to its return value. Try to do something reasonable.... */ + if (!s) + { + return 1; /* maybe there is a shell available? we can hope. :-P */ + } + block[0] = (uint32_t) s; + block[1] = strlen (s); + e = checkerror (call_host (SEMIHOSTING_SYS_SYSTEM, block)); + if ((e >= 0) && (e < 256)) + { + /* We have to convert e, an exit status to the encoded status of + the command. To avoid hard coding the exit status, we simply + loop until we find the right position. */ + int exit_code; + + for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1) + { + continue; + } + } + return e; +} + +int +_rename (const char* oldpath, const char* newpath) +{ + uint32_t block[4]; + block[0] = (uint32_t) oldpath; + block[1] = strlen (oldpath); + block[2] = (uint32_t) newpath; + block[3] = strlen (newpath); + return checkerror (call_host (SEMIHOSTING_SYS_RENAME, block)) ? -1 : 0; +} + +// ---------------------------------------------------------------------------- +// Required by Google Tests + +int +mkdir (const char *path __attribute__((unused)), + mode_t mode __attribute__((unused))) +{ +#if 0 + // always return true + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} + +char * +getcwd (char *buf, size_t size) +{ + // no cwd available via semihosting, so we use the temporary folder + strncpy (buf, "/tmp", size); + return buf; +} + +#endif // defined OS_USE_SEMIHOSTING + +#endif // __STDC_HOSTED__ == 1 diff --git a/source/system/stm32f4xx/assert.c b/source/system/stm32f4xx/assert.c new file mode 100644 index 0000000..19a48a0 --- /dev/null +++ b/source/system/stm32f4xx/assert.c @@ -0,0 +1,55 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +#include +#include +#include + +//#include "diag/Trace.h" + +// ---------------------------------------------------------------------------- + +void +__attribute__((noreturn)) +__assert_func (const char *file, int line, const char *func, + const char *failedexpr) +{ +// trace_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s\n", +// failedexpr, file, line, func ? ", function: " : "", +// func ? func : ""); + abort (); + /* NOTREACHED */ +} + +// ---------------------------------------------------------------------------- + +// This is STM32 specific, but can be used on other platforms too. +// If you need it, add the following to your application header: + +//#ifdef USE_FULL_ASSERT +//#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +//void assert_failed(uint8_t* file, uint32_t line); +//#else +//#define assert_param(expr) ((void)0) +//#endif // USE_FULL_ASSERT + +#if defined(USE_FULL_ASSERT) + +void +assert_failed (uint8_t* file, uint32_t line); + +// Called from the assert_param() macro, usually defined in the stm32f*_conf.h +void +__attribute__((noreturn, weak)) +assert_failed (uint8_t* file, uint32_t line) +{ +// trace_printf ("assert_param() failed: file \"%s\", line %d\n", file, line); + abort (); + /* NOTREACHED */ +} + +#endif // defined(USE_FULL_ASSERT) + +// ---------------------------------------------------------------------------- diff --git a/source/system/stm32f4xx/vectors_stm32f407xx.c b/source/system/stm32f4xx/vectors_stm32f407xx.c new file mode 100644 index 0000000..33ac1d4 --- /dev/null +++ b/source/system/stm32f4xx/vectors_stm32f407xx.c @@ -0,0 +1,335 @@ +// +// Copyright (c) 2015 Liviu Ionescu. +// This file was automatically generated by the xPacks scripts. +// + +// The list of external handlers is from the ARM assembly startup files. + +// ---------------------------------------------------------------------------- + +#include "ExceptionHandlers.h" + +// ---------------------------------------------------------------------------- + +void __attribute__((weak)) +Default_Handler(void); + +// Forward declaration of the specific IRQ handlers. These are aliased +// to the Default_Handler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions + +void __attribute__ ((weak, alias ("Default_Handler"))) +WWDG_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +PVD_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TAMP_STAMP_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +RTC_WKUP_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +FLASH_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +RCC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI0_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI4_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream0_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream4_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream5_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream6_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +ADC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN1_TX_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN1_RX0_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN1_RX1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN1_SCE_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI9_5_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM1_BRK_TIM9_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM1_UP_TIM10_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM1_TRG_COM_TIM11_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM1_CC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM4_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C1_EV_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C1_ER_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C2_EV_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C2_ER_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +SPI1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +SPI2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +USART1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +USART2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +USART3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +EXTI15_10_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +RTC_Alarm_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_FS_WKUP_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM8_BRK_TIM12_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM8_UP_TIM13_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM8_TRG_COM_TIM14_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM8_CC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA1_Stream7_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +FMC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +SDIO_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM5_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +SPI3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +UART4_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +UART5_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM6_DAC_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +TIM7_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream0_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream2_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream3_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream4_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +ETH_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +ETH_WKUP_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN2_TX_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN2_RX0_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN2_RX1_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +CAN2_SCE_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_FS_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream5_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream6_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DMA2_Stream7_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +USART6_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C3_EV_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +I2C3_ER_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_HS_EP1_OUT_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_HS_EP1_IN_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_HS_WKUP_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +OTG_HS_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +DCMI_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +HASH_RNG_IRQHandler(void); +void __attribute__ ((weak, alias ("Default_Handler"))) +FPU_IRQHandler(void); + +// ---------------------------------------------------------------------------- + +extern unsigned int _estack; + +typedef void +(* const pHandler)(void); + +// ---------------------------------------------------------------------------- + +// The table of interrupt handlers. It has an explicit section name +// and relies on the linker script to place it at the correct location +// in memory. + +__attribute__ ((section(".isr_vector"),used)) +pHandler __isr_vectors[] = + { + // Cortex-M Core Handlers + (pHandler) &_estack, // The initial stack pointer + Reset_Handler, // The reset handler + + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + MemManage_Handler, // The MPU fault handler + BusFault_Handler, // The bus fault handler + UsageFault_Handler, // The usage fault handler +#else + 0, // Reserved + 0, // Reserved + 0, // Reserved +#endif + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + DebugMon_Handler, // Debug monitor handler +#else + 0, // Reserved +#endif + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + // ---------------------------------------------------------------------- + // External Interrupts + WWDG_IRQHandler, // Window WatchDog + PVD_IRQHandler, // PVD through EXTI Line detection + TAMP_STAMP_IRQHandler, // Tamper and TimeStamps through the EXTI line + RTC_WKUP_IRQHandler, // RTC Wakeup through the EXTI line + FLASH_IRQHandler, // FLASH + RCC_IRQHandler, // RCC + EXTI0_IRQHandler, // EXTI Line0 + EXTI1_IRQHandler, // EXTI Line1 + EXTI2_IRQHandler, // EXTI Line2 + EXTI3_IRQHandler, // EXTI Line3 + EXTI4_IRQHandler, // EXTI Line4 + DMA1_Stream0_IRQHandler, // DMA1 Stream 0 + DMA1_Stream1_IRQHandler, // DMA1 Stream 1 + DMA1_Stream2_IRQHandler, // DMA1 Stream 2 + DMA1_Stream3_IRQHandler, // DMA1 Stream 3 + DMA1_Stream4_IRQHandler, // DMA1 Stream 4 + DMA1_Stream5_IRQHandler, // DMA1 Stream 5 + DMA1_Stream6_IRQHandler, // DMA1 Stream 6 + ADC_IRQHandler, // ADC1, ADC2 and ADC3s + CAN1_TX_IRQHandler, // CAN1 TX + CAN1_RX0_IRQHandler, // CAN1 RX0 + CAN1_RX1_IRQHandler, // CAN1 RX1 + CAN1_SCE_IRQHandler, // CAN1 SCE + EXTI9_5_IRQHandler, // External Line[9:5]s + TIM1_BRK_TIM9_IRQHandler, // TIM1 Break and TIM9 + TIM1_UP_TIM10_IRQHandler, // TIM1 Update and TIM10 + TIM1_TRG_COM_TIM11_IRQHandler, // TIM1 Trigger and Commutation and TIM11 + TIM1_CC_IRQHandler, // TIM1 Capture Compare + TIM2_IRQHandler, // TIM2 + TIM3_IRQHandler, // TIM3 + TIM4_IRQHandler, // TIM4 + I2C1_EV_IRQHandler, // I2C1 Event + I2C1_ER_IRQHandler, // I2C1 Error + I2C2_EV_IRQHandler, // I2C2 Event + I2C2_ER_IRQHandler, // I2C2 Error + SPI1_IRQHandler, // SPI1 + SPI2_IRQHandler, // SPI2 + USART1_IRQHandler, // USART1 + USART2_IRQHandler, // USART2 + USART3_IRQHandler, // USART3 + EXTI15_10_IRQHandler, // External Line[15:10]s + RTC_Alarm_IRQHandler, // RTC Alarm (A and B) through EXTI Line + OTG_FS_WKUP_IRQHandler, // USB OTG FS Wakeup through EXTI line + TIM8_BRK_TIM12_IRQHandler, // TIM8 Break and TIM12 + TIM8_UP_TIM13_IRQHandler, // TIM8 Update and TIM13 + TIM8_TRG_COM_TIM14_IRQHandler, // TIM8 Trigger and Commutation and TIM14 + TIM8_CC_IRQHandler, // TIM8 Capture Compare + DMA1_Stream7_IRQHandler, // DMA1 Stream7 + FMC_IRQHandler, // FMC + SDIO_IRQHandler, // SDIO + TIM5_IRQHandler, // TIM5 + SPI3_IRQHandler, // SPI3 + UART4_IRQHandler, // UART4 + UART5_IRQHandler, // UART5 + TIM6_DAC_IRQHandler, // TIM6 and DAC1&2 underrun errors + TIM7_IRQHandler, // TIM7 + DMA2_Stream0_IRQHandler, // DMA2 Stream 0 + DMA2_Stream1_IRQHandler, // DMA2 Stream 1 + DMA2_Stream2_IRQHandler, // DMA2 Stream 2 + DMA2_Stream3_IRQHandler, // DMA2 Stream 3 + DMA2_Stream4_IRQHandler, // DMA2 Stream 4 + ETH_IRQHandler, // Ethernet + ETH_WKUP_IRQHandler, // Ethernet Wakeup through EXTI line + CAN2_TX_IRQHandler, // CAN2 TX + CAN2_RX0_IRQHandler, // CAN2 RX0 + CAN2_RX1_IRQHandler, // CAN2 RX1 + CAN2_SCE_IRQHandler, // CAN2 SCE + OTG_FS_IRQHandler, // USB OTG FS + DMA2_Stream5_IRQHandler, // DMA2 Stream 5 + DMA2_Stream6_IRQHandler, // DMA2 Stream 6 + DMA2_Stream7_IRQHandler, // DMA2 Stream 7 + USART6_IRQHandler, // USART6 + I2C3_EV_IRQHandler, // I2C3 event + I2C3_ER_IRQHandler, // I2C3 error + OTG_HS_EP1_OUT_IRQHandler, // USB OTG HS End Point 1 Out + OTG_HS_EP1_IN_IRQHandler, // USB OTG HS End Point 1 In + OTG_HS_WKUP_IRQHandler, // USB OTG HS Wakeup through EXTI + OTG_HS_IRQHandler, // USB OTG HS + DCMI_IRQHandler, // DCMI + 0, // Reserved + HASH_RNG_IRQHandler, // Hash and Rng + FPU_IRQHandler, // FPU +}; + +// ---------------------------------------------------------------------------- + +// Processor ends up here if an unexpected interrupt occurs or a +// specific handler is not present in the application code. +// When in DEBUG, trigger a debug exception to clearly notify +// the user of the exception and help identify the cause. + +void __attribute__ ((section(".after_vectors"))) +Default_Handler(void) +{ +#if defined(DEBUG) +__DEBUG_BKPT(); +#endif +while (1) + { + } +} + +// ---------------------------------------------------------------------------- diff --git a/source/test/firmware/kernel/ringbuffer/Makefile b/source/test/firmware/kernel/ringbuffer/Makefile deleted file mode 100755 index fed86fd..0000000 --- a/source/test/firmware/kernel/ringbuffer/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -include ../../../../../config/make/rules.mk - -TEST_MAINFILE = $(TEST_EXE_DIR)cunit_ringbuffer -TEST_INCLUDES = \ - -I . \ - -I /usr/include \ - -I $(ROOT_DIR)/source/firmware/kernel - -TEST_SOURCES = \ - $(ROOT_DIR)/source/firmware/kernel/ringbuffer.c \ - $(ROOT_DIR)/source/test/firmware/kernel/ringbuffer/cunit_ringbuffer.c - -TEST_OBJECTS = $(TEST_SOURCES:$(SRC_DIR)/%.c=$(TEST_OBJ_DIR)/%.o) -TEST_DEPS = $(TEST_SOURCES:$(SRC_DIR)/%.c=$(TEST_OBJ_DIR)/%.d) - -TEST_CFLAGS = \ - $(CFLAGS) \ - $(TEST_INCLUDES) - -TEST_LDFLAGS = \ - $(LDFLAGS) \ - -lcunit - -all: $(TEST_MAINFILE) - -clean: - -rm -f $(TEST_OBJECTS) \ - $(TEST_DEPS) \ - $(TEST_MAINFILE) - -$(TEST_MAINFILE): $(TEST_OBJECTS) - @$(MKDIR) $(TEST_EXE_DIR) - $(NATIVE_CC) $(TEST_CFLAGS) $(TEST_LDFLAGS) $(TEST_OBJECTS) -o $(TEST_MAINFILE) - -$(TEST_OBJ_DIR)/%.o: $(SRC_DIR)/%.c - @$(MKDIR) $(dir $@) - $(call maketestdep,$<,$@,$(subst .o,.d,$@)) - $(NATIVE_CC) $(TEST_CFLAGS) -c $< -o $@ - -ifneq "$(MAKECMDGOALS)" "clean" --include $(TEST_DEPS) -endif diff --git a/source/test/firmware/kernel/ringbuffer/cpu.h b/source/test/firmware/kernel/ringbuffer/cpu.h deleted file mode 100755 index 6d39253..0000000 --- a/source/test/firmware/kernel/ringbuffer/cpu.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * cpu.h - * - * Created on: Nov 3, 2013 - * Author: tkl - */ - -#ifndef CPU_H_ -#define CPU_H_ - -#define disable_irq() -#define enable_irq() - -#endif /* CPU_H_ */ diff --git a/source/test/firmware/kernel/ringbuffer/cunit_ringbuffer.c b/source/test/firmware/kernel/ringbuffer/cunit_ringbuffer.c deleted file mode 100755 index 703ec6e..0000000 --- a/source/test/firmware/kernel/ringbuffer/cunit_ringbuffer.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - -#if 0 -#include -#endif - -#include "ringbuffer.h" - -static int init_suite(void) -{ - return 0; -} - -static int clean_suite(void) -{ - return 0; -} - -/* DUT */ -static char mem[10]; -static struct ringbuffer rb = { - mem, - mem, - mem, - sizeof(mem), - 0 -}; - -static void test_ringbuffer_size(void) -{ - char str[] = "0123456789ABCDEFGHI"; - CU_ASSERT(sizeof(mem) == ringbuffer_write(&rb, str, sizeof(str))); -} - -int main(void) -{ - /* test suite section */ - CU_pSuite suite = NULL; - if(CUE_SUCCESS != CU_initialize_registry()) - goto exit_2; - suite = CU_add_suite("list test suite", init_suite, clean_suite); - if(NULL == suite) - goto exit_1; - - /* test case section */ - if( - NULL == CU_add_test(suite, "ringbuffer size", test_ringbuffer_size) - ) - goto exit_1; - - /* basic interface using tests */ - CU_basic_set_mode(CU_BRM_VERBOSE); - CU_basic_run_tests(); - CU_basic_show_failures(CU_get_failure_list()); - -#if 0 - /* automated interface using tests */ - CU_automated_run_tests(); - CU_list_tests_to_file(); -#endif - -exit_1: - CU_cleanup_registry(); -exit_2: - return CU_get_error(); -}