CubeMX Configuration
Configure the STM32F407 project in STM32CubeMX with required peripherals (e.g., USART1 for console) and generate code using the Low-Layer (LL) drivers instead of HAL.
Code Modifications
-
Include RT-Thread Header In source files that use RT-Thread APIs, add:
#include <rtthread.h> -
Declare System Clock Function In
main.h, declare the clock configuration funciton if not already present:extern void SystemClock_Config(void); -
RT-Thread Configuration (
rtconfig.h) Customizertconfig.hto enable essential features:#ifndef __RTTHREAD_CFG_H__ #define __RTTHREAD_CFG_H__ #define RT_THREAD_PRIORITY_MAX 32 #define RT_TICK_PER_SECOND 1000 #define RT_ALIGN_SIZE 4 #define RT_NAME_MAX 8 #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN #define RT_MAIN_THREAD_STACK_SIZE 1024 #define RT_DEBUG #define RT_DEBUG_INIT 1 #define RT_USING_HOOK #define RT_USING_IDLE_HOOK #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 512 #define RT_USING_SEMAPHORE #define RT_USING_MUTEX #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE #define RT_USING_HEAP #define RT_USING_SMALL_MEM #define RT_USING_TINY_SIZE #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #include "finsh_config.h" #endif /* __RTTHREAD_CFG_H__ */ -
Board Initialization (
board.c) Implement hardware-specific initialization:#include <rthw.h> #include <rtthread.h> #include "main.h" #include "usart.h" #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) #define STM32_SRAM1_END (0x20020000) #if defined(__CC_ARM) || defined(__CLANG_ARM) extern int Image$$RW_IRAM1$$ZI$$Limit; #define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit) #endif #endif void SysTick_Handler(void) { rt_interrupt_enter(); rt_tick_increase(); rt_interrupt_leave(); } void rt_hw_board_init(void) { LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); SystemClock_Config(); SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) rt_system_heap_init((void *)HEAP_BEGIN, (void *)STM32_SRAM1_END); #endif } #ifdef RT_USING_CONSOLE #define CONSOLE_UART USART1 extern rt_bool_t usart1_ready; extern struct rt_mutex uart_tx_mutex; extern rt_bool_t mutex_initialized; void rt_hw_console_output(const char *str) { rt_size_t len = rt_strlen(str); if (mutex_initialized) rt_mutex_take(&uart_tx_mutex, RT_WAITING_FOREVER); if (usart1_ready) { for (rt_size_t i = 0; i < len; i++) { if (str[i] == '\n') { while (!LL_USART_IsActiveFlag_TXE(CONSOLE_UART)); LL_USART_TransmitData8(CONSOLE_UART, '\r'); } while (!LL_USART_IsActiveFlag_TXE(CONSOLE_UART)); LL_USART_TransmitData8(CONSOLE_UART, str[i]); } } if (mutex_initialized) rt_mutex_release(&uart_tx_mutex); } #endif #ifdef RT_USING_FINSH char rt_hw_console_getchar(void) { if (LL_USART_IsActiveFlag_RXNE(CONSOLE_UART)) return (char)LL_USART_ReceiveData8(CONSOLE_UART); else rt_thread_mdelay(10); return -1; } #endif -
USART Initialization Flag In
usart.c, set a global flag after USART1 is fully initialized:rt_bool_t usart1_ready = RT_FALSE; // ... inside MX_USART1_UART_Init() usart1_ready = RT_TRUE;Similarly, initiailze and manage a mutex for thread-safe UART output if needed.
With these changes, RT-Thread Nano runs on STM32F407 using LL drivers, and FinSH shell becomes available over USART1.