diff --git a/L1_MCU/STM32F429ZIT6_STARM/stm32f4xx_flash.ld b/L1_MCU/STM32F429ZIT6_STARM/stm32f4xx_flash.ld deleted file mode 100644 index bec9cb9..0000000 --- a/L1_MCU/STM32F429ZIT6_STARM/stm32f4xx_flash.ld +++ /dev/null @@ -1,269 +0,0 @@ -/* -****************************************************************************** -** - -** File : LinkerScript.ld -** -** Author : STM32CubeMX -** -** Abstract : Linker script for STM32F429ZITx series -** 2048Kbytes FLASH and 256Kbytes 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 -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -***************************************************************************** -** @attention -** -**

© COPYRIGHT(c) 2025 STMicroelectronics

-** -** Redistribution and use in source and binary forms, with or without modification, -** are permitted provided that the following conditions are met: -** 1. Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright notice, -** this list of conditions and the following disclaimer in the documentation -** and/or other materials provided with the distribution. -** 3. Neither the name of STMicroelectronics nor the names of its contributors -** may be used to endorse or promote products derived from this software -** without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Specify the memory areas */ -MEMORY -{ -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K -CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K -FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K -} - -/* Highest address of the user mode stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* 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) */ - *(.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 - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { - . = ALIGN(4); - *(.ARM.extab* .gnu.linkonce.armextab.*) - . = ALIGN(4); - } >FLASH - - .ARM (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { - . = ALIGN(4); - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - . = ALIGN(4); - } >FLASH - - .preinit_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { - . = ALIGN(4); - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - . = ALIGN(4); - } >FLASH - - .init_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { - . = ALIGN(4); - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); - } >FLASH - - .fini_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { - . = ALIGN(4); - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - . = ALIGN(4); - } >FLASH - - _siccmram = LOADADDR(.ccmram); - - /* CCM-RAM section - * - * IMPORTANT NOTE! - * If initialized variables will be placed in this section, - * the startup code needs to be modified to copy the init-values. - */ - .ccmram : - { - . = ALIGN(4); - _sccmram = .; /* create a global symbol at ccmram start */ - *(.ccmram) - *(.ccmram*) - - . = ALIGN(4); - _eccmram = .; /* create a global symbol at ccmram end */ - } >CCMRAM AT> FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - *(.RamFunc) /* .RamFunc sections */ - *(.RamFunc*) /* .RamFunc* sections */ - - . = ALIGN(4); - } >RAM AT> FLASH - - /* Initialized TLS data section */ - .tdata : ALIGN(4) - { - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - PROVIDE(__data_end = .); - PROVIDE(__tdata_end = .); - } >RAM AT> FLASH - - PROVIDE( __tdata_start = ADDR(.tdata) ); - PROVIDE( __tdata_size = __tdata_end - __tdata_start ); - - PROVIDE( __data_start = ADDR(.data) ); - PROVIDE( __data_size = __data_end - __data_start ); - - PROVIDE( __tdata_source = LOADADDR(.tdata) ); - PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); - PROVIDE( __tdata_source_size = __tdata_source_end - __tdata_source ); - - PROVIDE( __data_source = LOADADDR(.data) ); - PROVIDE( __data_source_end = __tdata_source_end ); - PROVIDE( __data_source_size = __data_source_end - __data_source ); - /* Uninitialized data section */ - .tbss (NOLOAD) : ALIGN(4) - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.tbss .tbss.*) - . = ALIGN(4); - PROVIDE( __tbss_end = . ); - } >RAM - - PROVIDE( __tbss_start = ADDR(.tbss) ); - PROVIDE( __tbss_size = __tbss_end - __tbss_start ); - PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); - - PROVIDE( __tls_base = __tdata_start ); - PROVIDE( __tls_end = __tbss_end ); - PROVIDE( __tls_size = __tls_end - __tls_base ); - PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); - PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1) ); - PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); - PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); - - .bss (NOLOAD) : ALIGN(4) - { - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - PROVIDE( __bss_end = .); - } >RAM - PROVIDE( __non_tls_bss_start = ADDR(.bss) ); - - PROVIDE( __bss_start = __tbss_start ); - PROVIDE( __bss_size = __bss_end - __bss_start ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack (NOLOAD) : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a:* ( * ) - libm.a:* ( * ) - libgcc.a:* ( * ) - } - -} diff --git a/L2_Core/hal/inc/ek_hal_base.h b/L2_Core/hal/inc/ek_hal_base.h deleted file mode 100644 index d2ed699..0000000 --- a/L2_Core/hal/inc/ek_hal_base.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef EK_HAL_BASE_H -#define EK_HAL_BASE_H - -#include "../../utils/inc/ek_def.h" -#include "../../utils/inc/ek_list.h" - -typedef enum -{ - // 通信类 - HAL_PERIPH_UART = 0, - HAL_PERIPH_USART, - HAL_PERIPH_SPI, - HAL_PERIPH_I2C, - HAL_PERIPH_I2S, - HAL_PERIPH_CAN, - HAL_PERIPH_USB, - HAL_PERIPH_SDIO, - - // 定时器类 - HAL_PERIPH_TIM, - HAL_PERIPH_PWM, - HAL_PERIPH_WWDG, - HAL_PERIPH_IWDG, - HAL_PERIPH_RTC, - - // 模拟类 - HAL_PERIPH_ADC, - HAL_PERIPH_DAC, - - // GPIO和中断 - HAL_PERIPH_GPIO, - HAL_PERIPH_EXTI, - - // DMA - HAL_PERIPH_DMA, - - // 存储 - HAL_PERIPH_FLASH, - - // 系统类 - HAL_PERIPH_PWR, - HAL_PERIPH_RCC, - - // 特殊功能 - HAL_PERIPH_RNG, - - HAL_PERIPH_MAX, -} ek_hal_periph_type_t; - -typedef struct ek_hal_base_t ek_hal_base_t; - -struct ek_hal_base_t -{ - uint8_t idx; - ek_hal_periph_type_t type; - ek_list_node_t node; -}; - -#endif /* EK_HAL_BASE_H */ diff --git a/L2_Core/hal/inc/ek_hal_gpio.h b/L2_Core/hal/inc/ek_hal_gpio.h new file mode 100644 index 0000000..7882d1f --- /dev/null +++ b/L2_Core/hal/inc/ek_hal_gpio.h @@ -0,0 +1,25 @@ +#ifndef EK_HAL_GPIO_H +#define EK_HAL_GPIO_H + +#include "../../utils/inc/ek_def.h" +#include "../../utils/inc/ek_list.h" + +typedef struct ek_hal_gpio_t ek_hal_gpio_t; + +struct ek_hal_gpio_t +{ + uint8_t idx; + ek_list_node_t node; + + void (*set)(void); + void (*reset)(void); + void (*toggle)(void); +}; + +extern ek_list_node_t ek_hal_gpio_head; + +extern ek_hal_gpio_t hal_drv_gpio_xxx_pin; + +void ek_hal_gpio_init(void); + +#endif // EK_HAL_GPIO_H diff --git a/L2_Core/hal/inc/ek_hal_spi.h b/L2_Core/hal/inc/ek_hal_spi.h new file mode 100644 index 0000000..25cc01e --- /dev/null +++ b/L2_Core/hal/inc/ek_hal_spi.h @@ -0,0 +1,28 @@ +#ifndef EK_HAL_SPI_H +#define EK_HAL_SPI_H + +#include "../../utils/inc/ek_def.h" +#include "../../utils/inc/ek_list.h" + +typedef struct ek_hal_spi_t ek_hal_spi_t; + +struct ek_hal_spi_t +{ + uint8_t idx; + ek_list_node_t node; + + bool lock; + + void (*init)(void); + bool (*write)(uint8_t *txdata, size_t size); + bool (*read)(uint8_t *rxdata, size_t size); + bool (*write_read)(uint8_t *txdata, uint8_t *rxdata, size_t size); +}; + +extern ek_list_node_t ek_hal_spi_head; + +extern ek_hal_spi_t hal_drv_spi1; + +void ek_hal_spi_init(void); + +#endif // EK_HAL_SPI_H diff --git a/L2_Core/hal/inc/ek_hal_tick.h b/L2_Core/hal/inc/ek_hal_tick.h new file mode 100644 index 0000000..86e8717 --- /dev/null +++ b/L2_Core/hal/inc/ek_hal_tick.h @@ -0,0 +1,20 @@ +#ifndef EK_HAL_TICK_H +#define EK_HAL_TICK_H + +#include "../../utils/inc/ek_def.h" + +typedef struct ek_hal_tick_t ek_hal_tick_t; + +struct ek_hal_tick_t +{ + uint8_t idx; + uint16_t ms_per_tick; + uint32_t tick_to_wait; + + uint32_t (*get)(void); + void (*delay)(uint32_t xtick); +}; + +extern ek_hal_tick_t ek_default_ticker; + +#endif // EK_HAL_TICK_H diff --git a/L2_Core/hal/inc/ek_hal_uart.h b/L2_Core/hal/inc/ek_hal_uart.h index 25fc86d..0678999 100644 --- a/L2_Core/hal/inc/ek_hal_uart.h +++ b/L2_Core/hal/inc/ek_hal_uart.h @@ -1,18 +1,30 @@ #ifndef EK_HAL_UART_H #define EK_HAL_UART_H -#include "ek_hal_base.h" +#include "../../utils/inc/ek_def.h" +#include "../../utils/inc/ek_list.h" -typedef struct hal_ek_uart_t hal_ek_uart_t; +typedef struct ek_hal_uart_t ek_hal_uart_t; -struct hal_ek_uart_t +struct ek_hal_uart_t { - ek_hal_base_t base; - + uint8_t idx; uint32_t baudrate; + uint16_t buf_size; + uint8_t *rxbuffer; + ek_list_node_t node; + + bool lock; - bool (*write)(void *src, size_t size); - bool (*read)(void *dst, size_t size); + void (*init)(void); + bool (*write)(uint8_t *txdata, size_t size); + void (*read)(void); }; -#endif /* EK_HAL_UART_H */ +extern ek_list_node_t ek_hal_uart_head; + +extern ek_hal_uart_t hal_drv_uart1; + +void ek_hal_uart_init(void); + +#endif // EK_HAL_UART_H diff --git a/L2_Core/hal/src/ek_hal_gpio.c b/L2_Core/hal/src/ek_hal_gpio.c new file mode 100644 index 0000000..1b5f244 --- /dev/null +++ b/L2_Core/hal/src/ek_hal_gpio.c @@ -0,0 +1,35 @@ +#include "../inc/ek_hal_gpio.h" +#include "../../utils/inc/ek_export.h" + +ek_list_node_t ek_hal_gpio_head; + +static void xxx_pin_set(void); +static void xxx_pin_reset(void); +static void xxx_pin_toggle(void); + +ek_hal_gpio_t hal_drv_gpio_xxx_pin = { + .idx = 1, + .reset = xxx_pin_set, + .set = xxx_pin_reset, + .toggle = xxx_pin_toggle, +}; + +static void xxx_pin_set(void) +{ +} + +static void xxx_pin_reset(void) +{ +} + +static void xxx_pin_toggle(void) +{ +} + +void ek_hal_gpio_init(void) +{ + ek_list_init(&ek_hal_gpio_head); + ek_list_add_tail(&ek_hal_gpio_head, &hal_drv_gpio_xxx_pin.node); +} + +EK_EXPORT(ek_hal_gpio_init, 0); diff --git a/L2_Core/hal/src/ek_hal_spi.c b/L2_Core/hal/src/ek_hal_spi.c new file mode 100644 index 0000000..7683cf4 --- /dev/null +++ b/L2_Core/hal/src/ek_hal_spi.c @@ -0,0 +1,91 @@ +#include "../inc/ek_hal_spi.h" +#include "../../utils/inc/ek_assert.h" +#include "../../utils/inc/ek_export.h" + +#define EK_HAL_LOCK_ON(x) ((x)->lock = true) +#define EK_HAL_LOCK_OFF(x) ((x)->lock = false) +#define EK_HAL_LOCK_TEST(x) ((x)->lock == true) + +#define STM32F429XX_TIMEOUT (100) + +ek_list_node_t ek_hal_spi_head; + +static void spi1_init(void); +static bool spi1_send(uint8_t *txdata, size_t size); +static bool spi1_recieve(uint8_t *rxdata, size_t size); +static bool spi1_write_recieve(uint8_t *txdata, uint8_t *rxdata, size_t size); + +ek_hal_spi_t hal_drv_spi1 = { + .idx = 1, + .lock = false, + + .init = spi1_init, + .read = spi1_recieve, + .write = spi1_send, + .write_read = spi1_write_recieve, +}; + +static void spi1_init(void) +{ + hal_drv_spi1.lock = false; + + ek_list_add_tail(&ek_hal_spi_head, &hal_drv_spi1.node); +} + +static bool spi1_send(uint8_t *txdata, size_t size) +{ + if (EK_HAL_LOCK_TEST(&hal_drv_spi1)) return false; + + EK_HAL_LOCK_ON(&hal_drv_spi1); + + __UNUSED(txdata); + __UNUSED(size); + + EK_HAL_LOCK_OFF(&hal_drv_spi1); + + return true; +} + +static bool spi1_recieve(uint8_t *rxdata, size_t size) +{ + if (EK_HAL_LOCK_TEST(&hal_drv_spi1)) return false; + + EK_HAL_LOCK_ON(&hal_drv_spi1); + + __UNUSED(rxdata); + __UNUSED(size); + + EK_HAL_LOCK_OFF(&hal_drv_spi1); + + return true; +} + +static bool spi1_write_recieve(uint8_t *txdata, uint8_t *rxdata, size_t size) +{ + if (EK_HAL_LOCK_TEST(&hal_drv_spi1)) return false; + + EK_HAL_LOCK_ON(&hal_drv_spi1); + + __UNUSED(txdata); + __UNUSED(rxdata); + __UNUSED(size); + + EK_HAL_LOCK_OFF(&hal_drv_spi1); + + return true; +} + +void ek_hal_spi_init(void) +{ + ek_list_node_t *p; + ek_list_init(&ek_hal_spi_head); + + spi1_init(); + + ek_list_iterate(p, &ek_hal_spi_head) + { + ek_hal_spi_t *spi = (ek_hal_spi_t *)ek_list_container(p, ek_hal_spi_t, node); + } +} + +EK_EXPORT(ek_hal_spi_init, 0); diff --git a/L2_Core/hal/src/ek_hal_tick.c b/L2_Core/hal/src/ek_hal_tick.c new file mode 100644 index 0000000..cdd2f30 --- /dev/null +++ b/L2_Core/hal/src/ek_hal_tick.c @@ -0,0 +1,20 @@ +#include "../inc/ek_hal_tick.h" + +static uint32_t defualt_get_tick(void); +static void default_delay(uint32_t xticks); + +ek_hal_tick_t ek_default_ticker = { + .idx = 1, .ms_per_tick = 1, .tick_to_wait = 0, .get = defualt_get_tick, .delay = default_delay}; + +static uint32_t defualt_get_tick(void) +{ + // 这里放置一个系统返回函数 e.g. HAL_GetTick() + return 0; +} + +static void default_delay(uint32_t xticks) +{ + ek_default_ticker.tick_to_wait = ek_default_ticker.get() + xticks; + + while (ek_default_ticker.tick_to_wait >= ek_default_ticker.get()); +} diff --git a/L2_Core/hal/src/ek_hal_uart.c b/L2_Core/hal/src/ek_hal_uart.c new file mode 100644 index 0000000..264cc62 --- /dev/null +++ b/L2_Core/hal/src/ek_hal_uart.c @@ -0,0 +1,70 @@ +#include "../inc/ek_hal_uart.h" +#include "../../utils/inc/ek_mem.h" +#include "../../utils/inc/ek_assert.h" +#include "../../utils/inc/ek_export.h" + + +#define EK_HAL_LOCK_ON(x) ((x)->lock = true) +#define EK_HAL_LOCK_OFF(x) ((x)->lock = false) +#define EK_HAL_LOCK_TEST(x) ((x)->lock == true) + +#define UART_RX_BUFFER_SIZE 128 + +ek_list_node_t ek_hal_uart_head; + +static uint8_t uart1_rx_buffer[UART_RX_BUFFER_SIZE]; // 建议通过串口 + 空闲终端 + DMA将数据搬运到这个数组 +static void uart1_uart_init(void); +static bool uart1_uart_send(uint8_t *TxData, size_t Size); +static void uart1_uart_recieve_to_idle(void); + +ek_hal_uart_t hal_drv_uart1 = {.idx = 1, + .baudrate = 115200, + .buf_size = UART_RX_BUFFER_SIZE, + .rxbuffer = uart1_rx_buffer, + + .init = uart1_uart_init, + .write = uart1_uart_send, + .read = uart1_uart_recieve_to_idle}; + +static void uart1_uart_init(void) +{ + hal_drv_uart1.lock = false; + + ek_list_add_tail(&ek_hal_uart_head, &hal_drv_uart1.node); +} + +static bool uart1_uart_send(uint8_t *txdata, size_t size) +{ + if (EK_HAL_LOCK_TEST(&hal_drv_uart1)) return false; + + EK_HAL_LOCK_ON(&hal_drv_uart1); + + __UNUSED(txdata); + __UNUSED(size); + // 放置具体串口发送的底层 + + EK_HAL_LOCK_OFF(&hal_drv_uart1); + + return true; +} + +static void uart1_uart_recieve_to_idle(void) +{ + // 建议使用串口+空闲中断+DMA接收数据 +} + +void ek_hal_uart_init(void) +{ + ek_list_node_t *p; + ek_list_init(&ek_hal_uart_head); + + uart1_uart_init(); + + ek_list_iterate(p, &ek_hal_uart_head) + { + ek_hal_uart_t *uart = (ek_hal_uart_t *)ek_list_container(p, ek_hal_uart_t, node); + uart->read(); + } +} + +EK_EXPORT(ek_hal_uart_init, 0); \ No newline at end of file diff --git a/L2_Core/utils/inc/ek_export.h b/L2_Core/utils/inc/ek_export.h new file mode 100644 index 0000000..ec23d27 --- /dev/null +++ b/L2_Core/utils/inc/ek_export.h @@ -0,0 +1,36 @@ +#ifndef EK_EXPORT_H +#define EK_EXPORT_H + +#include "../../../ek_conf.h" + +#if (EK_EXPORT_ENABLE == 1) + +/* +* @note 使用这个模块请在对应的 .ld 中 SECTOINS 部分添加下列的部分: +* .ek_export : +* { +* . = ALIGN(4); +* _ek_export_fn_start = .; +* KEEP(*(SORT(.ek_export_fn*))) +* . = ALIGN(4); +* _ek_export_fn_end = .; +* } > flash +*/ + +typedef void (*_ek_export_init_fn_t)(void); + +# define _EK_STR_HELPER(x) #x +# define _EK_STR(x) _EK_STR_HELPER(x) + +# define EK_EXPORT(fn, prio) \ + const _ek_export_init_fn_t __init_##fn##prio __attribute__((used, section(".ek_export_fn." _EK_STR(prio)))) = fn + +#else + +# define EK_EXPORT(fn, prio) + +#endif /* EK_EXPORT_ENABLE */ + +void ek_export_init(void); + +#endif /* EK_EXPORT_H */ diff --git a/L2_Core/utils/src/ek_export.c b/L2_Core/utils/src/ek_export.c new file mode 100644 index 0000000..43920e0 --- /dev/null +++ b/L2_Core/utils/src/ek_export.c @@ -0,0 +1,28 @@ +#include "../inc/ek_export.h" + +#if (EK_EXPORT_ENABLE == 1) + +# include "../inc/ek_assert.h" + +extern _ek_export_init_fn_t _ek_export_fn_start; +extern _ek_export_init_fn_t _ek_export_fn_end; + +void ek_export_init(void) +{ + _ek_export_init_fn_t *fn_ptr; + + for (fn_ptr = &_ek_export_fn_start; fn_ptr < &_ek_export_fn_end; fn_ptr++) + { + ek_assert_tiny(*fn_ptr != NULL); + + (*fn_ptr)(); + } +} + +#else + +void ek_export_init(void) +{ +} + +#endif /* EK_EXPORT_ENABLE */ diff --git a/L5_App/src/ek_app.c b/L5_App/src/ek_app.c index 333fccb..e015ee0 100644 --- a/L5_App/src/ek_app.c +++ b/L5_App/src/ek_app.c @@ -2,6 +2,9 @@ #include "ek_mem.h" #include "ek_io.h" #include "ek_log.h" +#include "ek_export.h" + +#include "ek_hal_tick.h" EK_LOG_FILE_TAG("ek_app.c"); @@ -13,15 +16,14 @@ EK_IO_FPUTC() EK_LOG_GET_TICK() { - // 这里返回你系统的tick - // e.g. return HAL_GetTick(); - return 0; + return ek_default_ticker.get(); } void ek_main(void) { ek_heap_init(); ek_io_init(); + ek_export_init(); while (1) { diff --git a/cmake/arm-compile6.cmake b/cmake/arm-compile6.cmake deleted file mode 100644 index e5b4c9f..0000000 --- a/cmake/arm-compile6.cmake +++ /dev/null @@ -1,126 +0,0 @@ -# ============================================================================= -# 基础系统与编译器识别 -# ============================================================================= -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_SYSTEM_PROCESSOR arm) - -# [注意] 这里使用的是 "Clang",不是 "ARMClang" -# 这意味着 CMake 会把它当做标准 LLVM 处理,支持 GCC 风格的参数 -set(CMAKE_C_COMPILER_ID Clang) -set(CMAKE_CXX_COMPILER_ID Clang) - -# ============================================================================= -# 工具链路径配置 -# ============================================================================= -# [需修改] ST 的 LLVM 工具链前缀是 "starm-" -# 确保你的环境变量里已经有 STM32CubeCLT 的 bin 目录 -set(TOOLCHAIN_PREFIX starm-) - -set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}clang) -set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}clang++) -set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}clang) # 链接器也用 clang 前端调用 -set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) -set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) - -set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") -set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") -set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") - -# 同样,跳过可执行文件检查,防止配置阶段报错 -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - -# ============================================================================= -# 核心配置开关 (ST 工具链特有功能) -# ============================================================================= -# ST 提供了三种库模式,你可以根据需要修改这个变量: -# "STARM_HYBRID" : 混合模式 (Clang 编译器 + GNU 链接器/库) -# "STARM_NEWLIB" : 纯 Clang + Newlib 库 (标准嵌入式库) -# "STARM_PICOLIBC" : 纯 Clang + Picolibc (更小、更快的现代化库,强烈推荐) -set(STARM_TOOLCHAIN_CONFIG "STARM_PICOLIBC") - -# 根据上面的选择,自动设置库的路径和配置文件 -if(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") - # 混合模式需要指定 GNU 工具链的位置 - set(TOOLCHAIN_MULTILIBS "--multi-lib-config=\"$ENV{CLANG_GCC_CMSIS_COMPILER}/multilib.gnu_tools_for_stm32.yaml\" --gcc-toolchain=\"$ENV{GCC_TOOLCHAIN_ROOT}/..\"") -elseif (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") - set(TOOLCHAIN_MULTILIBS "--config=newlib.cfg") -endif() - -# ============================================================================= -# 芯片架构参数 (针对 STM32F429) -# ============================================================================= -# [需修改] 核心参数:STM32F429 是 M4 核,带硬件浮点 -# -mcpu=cortex-m4 : F4 系列核心 -# -mfpu=fpv4-sp-d16 : F4 的浮点单元版本 -# -mfloat-abi=hard : 开启硬件浮点 (若用 FreeRTOS 需确保配置匹配) -set(TARGET_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard") - -# ============================================================================= -# 编译器选项 (Compiler Flags) -# ============================================================================= -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") -set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MP") - -# -Wall: 开启警告 -# -fdata-sections -ffunction-sections: 配合链接器的 gc-sections 裁剪体积 -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") - -# 调试/发布模式预设 -# -Og: 针对调试优化的等级 (比 -O0 稍微优化一点,但能看清变量) -# -Oz: LLVM 特有的"超级体积优化" (比 GCC 的 -Os 更激进) -set(CMAKE_C_FLAGS_DEBUG "-Og -g3") -set(CMAKE_C_FLAGS_RELEASE "-Oz -g0") -set(CMAKE_CXX_FLAGS_DEBUG "-Og -g3") -set(CMAKE_CXX_FLAGS_RELEASE "-Oz -g0") - -set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") - -# ============================================================================= -# 链接脚本配置 -# ============================================================================= -# 定义变量 LINKER_SCRIPT -# CACHE FILEPATH: 表示这是一个缓存变量,类型为文件路径,可以在命令行被 -D 覆盖 -# 默认值: 设置为你原本的路径 -set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/L1_MCU/STM32F429ZIT6/STM32F429XX_FLASH.ld" - CACHE FILEPATH "The path to the linker script") - -if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeScratch") - if(NOT EXISTS "${LINKER_SCRIPT}") - message(WARNING "Linker script not found at: ${LINKER_SCRIPT}") - endif() -endif() - -# ============================================================================= -# 链接器选项 (Linker Flags) -# ============================================================================= -set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") - -# 根据所选的 C 库模式,链接不同的启动文件 (Startup Files) -if (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") - # 混合模式使用 GCC 的 nano.specs - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --gcc-specs=nano.specs") - set(TOOLCHAIN_LINK_LIBRARIES "m") - -elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") - # 链接 Newlib 的启动代码 - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-nosys") - -elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_PICOLIBC") - # 链接 Picolibc 的启动代码 - # -lcrt0-hosted: 包含基本的 CRT0 启动代码 - # -z norelro: 禁用 Relocation Read-Only (为了节省 RAM) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-hosted -z norelro") -endif() - -# 因为 starm-clang 实际上是调用 ld.lld 或 arm-ld,所以使用 GCC 风格的 -T -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${LINKER_SCRIPT}\"") - -# 生成 Map 文件 -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map") -# 裁剪未使用的段 (Dead Code Elimination) -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -# 禁止栈执行 (安全特性) -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") -# 打印内存占用 -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage ") diff --git a/cmake/gcc-arm-none-eabi.cmake b/cmake/gcc-arm-none-eabi.cmake index 6a4ecb6..93e0038 100644 --- a/cmake/gcc-arm-none-eabi.cmake +++ b/cmake/gcc-arm-none-eabi.cmake @@ -1,15 +1,9 @@ -# ============================================================================= -# 基础系统配置 (一般不用改) -# ============================================================================= set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_C_COMPILER_ID GNU) set(CMAKE_CXX_COMPILER_ID GNU) -# ============================================================================= -# 工具链路径配置 -# ============================================================================= -# [需修改] 如果你的编译器没加环境变量,要在下面手动指定绝对路径 +# 工具链前缀,确保在 PATH 中或使用绝对路径 set(TOOLCHAIN_PREFIX arm-none-eabi-) set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) @@ -22,16 +16,9 @@ set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") - -# 关键:跳过编译可执行文件测试,防止配置阶段报错 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -# ============================================================================= -# 链接脚本配置 -# ============================================================================= -# 定义变量 LINKER_SCRIPT -# CACHE FILEPATH: 表示这是一个缓存变量,类型为文件路径,可以在命令行被 -D 覆盖 -# 默认值: 设置为你原本的路径 +# 链接脚本路径 (可通过 -DLINKER_SCRIPT 覆盖) set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/L1_MCU/STM32F429ZIT6/stm32f429xx_flash.ld" CACHE FILEPATH "The path to the linker script") @@ -41,46 +28,23 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeScratch") endif() endif() -# ============================================================================= -# 芯片架构参数 (针对 STM32F429) -# ============================================================================= -# [需修改] 核心参数:STM32F429 是 M4 核,带硬件浮点 -# -mcpu=cortex-m4 : F4 系列核心 -# -mfpu=fpv4-sp-d16 : F4 的浮点单元版本 -# -mfloat-abi=hard : 开启硬件浮点 (若用 FreeRTOS 需确保配置匹配) +# 芯片架构: Cortex-M4 with FPU set(TARGET_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard") - -# ============================================================================= -# 编译器选项 (Compiler Flags) -# ============================================================================= set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") -# -fdata-sections -ffunction-sections : 为每个函数生成独立段,方便最后删减体积 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") -# 调试/发布模式预设 set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") set(CMAKE_C_FLAGS_RELEASE "-Os -g0") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") set(CMAKE_CXX_FLAGS_RELEASE "-Os -g0") -# C++ 特有优化 (禁用异常和RTTI,节省空间) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") -# ============================================================================= -# 链接器选项 (Linker Flags) -# ============================================================================= set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") - -# 指定链接脚本 (.ld) 的路径 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${LINKER_SCRIPT}\"") - -# 使用 newlib-nano (嵌入式专用微型库) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs") - -# 生成 Map 文件并删除未使用的函数 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") -# 打印内存占用 (Flash/RAM) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage") set(TOOLCHAIN_LINK_LIBRARIES "m") diff --git a/cmake/starm-clang.cmake b/cmake/starm-clang.cmake index 0de1d9f..5146ead 100644 --- a/cmake/starm-clang.cmake +++ b/cmake/starm-clang.cmake @@ -1,18 +1,9 @@ -# ============================================================================= -# 基础系统配置 -# ============================================================================= set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR arm) - -# 注意:ST 的工具链本质是 LLVM/Clang,所以 ID 设为 Clang set(CMAKE_C_COMPILER_ID Clang) set(CMAKE_CXX_COMPILER_ID Clang) -# ============================================================================= -# 工具链路径配置 -# ============================================================================= -# [需修改] 确保 'starm-' 在你的环境变量 PATH 中,或者写绝对路径 -# 例如 C:/ST/STM32CubeCLT/STLink-gdb-server/bin/starm- +# 工具链前缀,确保在 PATH 中或使用绝对路径 set(TOOLCHAIN_PREFIX starm-) set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}clang) @@ -25,45 +16,23 @@ set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") - -# 跳过编译检查,防止配置阶段报错 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -# ============================================================================= -# C 库模式选择 (ST工具链特有) -# ============================================================================= -# [可修改] 选择使用的 C 库类型: -# "STARM_PICOLIBC" : (推荐) 专为嵌入式优化的现代化 C 库,体积小,速度快 -# "STARM_NEWLIB" : 传统的嵌入式 C 库 -# "STARM_HYBRID" : 混合模式 (Clang 编译器 + GNU 库) +# C 库选择: STARM_PICOLIBC / STARM_NEWLIB / STARM_HYBRID set(STARM_TOOLCHAIN_CONFIG "STARM_PICOLIBC") -# 根据选择配置库路径 (通常不需要改) if(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") set(TOOLCHAIN_MULTILIBS "--multi-lib-config=\"$ENV{CLANG_GCC_CMSIS_COMPILER}/multilib.gnu_tools_for_stm32.yaml\" --gcc-toolchain=\"$ENV{GCC_TOOLCHAIN_ROOT}/..\"") elseif (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") set(TOOLCHAIN_MULTILIBS "--config=newlib.cfg") endif() -# ============================================================================= -# 芯片架构参数 (针对 STM32F429) -# ============================================================================= -# [需修改] F429 是 Cortex-M4F 核心 -# -mcpu=cortex-m4 : 核心类型 -# -mfpu=fpv4-sp-d16 : F429 的 FPU 版本 (单精度) -# -mfloat-abi=hard : 开启硬件浮点 +# 芯片架构: Cortex-M4 with FPU set(TARGET_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ${TOOLCHAIN_MULTILIBS}") - -# ============================================================================= -# 编译器选项 (Compiler Flags) -# ============================================================================= set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MP") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") -# 调试/发布预设 -# -Og: 调试友好优化 -# -Oz: 极致体积优化 (LLVM 特有) set(CMAKE_C_FLAGS_DEBUG "-Og -g3") set(CMAKE_C_FLAGS_RELEASE "-Oz -g0") set(CMAKE_CXX_FLAGS_DEBUG "-Og -g3") @@ -71,12 +40,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "-Oz -g0") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") -# ============================================================================= -# 链接脚本配置 -# ============================================================================= -# 定义变量 LINKER_SCRIPT -# CACHE FILEPATH: 表示这是一个缓存变量,类型为文件路径,可以在命令行被 -D 覆盖 -# 默认值: 设置为你原本的路径 +# 链接脚本路径 (可通过 -DLINKER_SCRIPT 覆盖) set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/L1_MCU/STM32F429ZIT6/stm32f429xx_flash.ld" CACHE FILEPATH "The path to the linker script") @@ -86,30 +50,17 @@ if(NOT CMAKE_SOURCE_DIR MATCHES "CMakeScratch") endif() endif() - -# ============================================================================= -# 链接器选项 (Linker Flags) -# ============================================================================= set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") - -# 库启动文件配置 if (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --gcc-specs=nano.specs") set(TOOLCHAIN_LINK_LIBRARIES "m") elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-nosys") elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_PICOLIBC") - # Picolibc 启动配置 - # -lcrt0-hosted : 包含标准启动代码 (替代 startup.s 中的部分功能) - # -z norelro : 禁用只读重定位,节省 RAM set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-hosted -z norelro") endif() -# [需修改] 指定链接脚本 (.ld) -# 请确保该文件路径正确,通常在 L1_MCU 目录下 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${LINKER_SCRIPT}\"") - -# 生成 Map 文件、裁剪未使用的段、打印内存占用 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage") diff --git a/ek_conf.h b/ek_conf.h index cee8b8d..9141212 100644 --- a/ek_conf.h +++ b/ek_conf.h @@ -24,6 +24,7 @@ /* ======================================================================== * 模块功能开关 + * - EK_EXPORT_ENABLE: 使能自动初始化 * - EK_IO_ENABLE: 使能IO库(基于lwprintf) * - EK_LOG_ENABLE: 使能日志模块 * - EK_LIST_ENABLE: 使能链表模块 @@ -32,6 +33,7 @@ * - EK_STACK_ENABLE: 使能栈模块 * - EK_SHELL_ENABLE: 使能shell模块 * ======================================================================== */ +#define EK_EXPORT_ENABLE (0) #define EK_IO_ENABLE (1) #define EK_LOG_ENABLE (1) #define EK_LIST_ENABLE (1)