| @@ -22,6 +22,7 @@ | |||||
| /* Private includes ----------------------------------------------------------*/ | /* Private includes ----------------------------------------------------------*/ | ||||
| /* USER CODE BEGIN Includes */ | /* USER CODE BEGIN Includes */ | ||||
| /* uC/OS-II的公开接口、任务类型和配置宏都由此头文件提供。 */ | |||||
| #include "ucos_ii.h" | #include "ucos_ii.h" | ||||
| /* USER CODE END Includes */ | /* USER CODE END Includes */ | ||||
| @@ -51,6 +52,12 @@ static volatile uint32_t uart1_tx_ok_count; | |||||
| static volatile uint32_t uart1_tx_busy_count; | static volatile uint32_t uart1_tx_busy_count; | ||||
| static volatile uint32_t uart1_tx_error_count; | static volatile uint32_t uart1_tx_error_count; | ||||
| static volatile uint32_t uart1_tx_complete_count; | static volatile uint32_t uart1_tx_complete_count; | ||||
| /* | |||||
| * 每个任务必须拥有独立栈空间。 | |||||
| * OS_STK在本工程中为32位,因此256个OS_STK占用1024字节RAM。 | |||||
| * Cortex-M栈从高地址向低地址增长,创建任务时要把数组末元素作为栈顶传入。 | |||||
| */ | |||||
| static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; | static OS_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; | ||||
| /* USER CODE END PV */ | /* USER CODE END PV */ | ||||
| @@ -69,14 +76,21 @@ static void AppTaskStart(void *p_arg); | |||||
| /* Private user code ---------------------------------------------------------*/ | /* Private user code ---------------------------------------------------------*/ | ||||
| /* USER CODE BEGIN 0 */ | /* USER CODE BEGIN 0 */ | ||||
| /* | |||||
| * uC/OS-II任务函数的固定形式是 void Task(void *p_arg)。 | |||||
| * 任务通常包含一个永久循环;需要等待时应调用OS延时或等待内核对象, | |||||
| * 让出CPU给其他就绪任务,而不是在任务里忙等待。 | |||||
| */ | |||||
| static void AppTaskStart(void *p_arg) | static void AppTaskStart(void *p_arg) | ||||
| { | { | ||||
| HAL_StatusTypeDef uart_status; | HAL_StatusTypeDef uart_status; | ||||
| /* 当前没有给任务传递参数,显式转换可避免编译器产生未使用警告。 */ | |||||
| (void)p_arg; | (void)p_arg; | ||||
| while (1) | while (1) | ||||
| { | { | ||||
| /* DMA发送启动后立即返回,真正的发送完成由DMA中断回调通知。 */ | |||||
| uart_status = HAL_UART_Transmit_DMA(&huart1, | uart_status = HAL_UART_Transmit_DMA(&huart1, | ||||
| (uint8_t *)uart1_test_message, | (uint8_t *)uart1_test_message, | ||||
| sizeof(uart1_test_message) - 1U); | sizeof(uart1_test_message) - 1U); | ||||
| @@ -94,6 +108,11 @@ static void AppTaskStart(void *p_arg) | |||||
| uart1_tx_error_count++; | uart1_tx_error_count++; | ||||
| } | } | ||||
| /* | |||||
| * 把当前任务延时OS_TICKS_PER_SEC个系统节拍。 | |||||
| * 当前OS_TICKS_PER_SEC为1000,SysTick周期为1ms,因此这里延时1秒。 | |||||
| * 延时期间任务处于等待态,内核会调度其他就绪任务(目前主要是空闲任务)。 | |||||
| */ | |||||
| OSTimeDly(OS_TICKS_PER_SEC); | OSTimeDly(OS_TICKS_PER_SEC); | ||||
| } | } | ||||
| } | } | ||||
| @@ -134,8 +153,27 @@ int main(void) | |||||
| MX_USB_DEVICE_Init(); | MX_USB_DEVICE_Init(); | ||||
| MX_USART1_UART_Init(); | MX_USART1_UART_Init(); | ||||
| /* USER CODE BEGIN 2 */ | /* USER CODE BEGIN 2 */ | ||||
| /* uC/OS-II接口通常用返回错误码的方式报告执行结果。 */ | |||||
| INT8U os_err; | INT8U os_err; | ||||
| /* | |||||
| * 初始化内核的任务表、就绪表、事件控制块等内部数据。 | |||||
| * OSInit()只完成初始化,此时任务调度尚未开始。 | |||||
| */ | |||||
| OSInit(); | OSInit(); | ||||
| /* | |||||
| * 创建应用启动任务,各参数依次为: | |||||
| * 1. 任务入口函数; | |||||
| * 2. 传给任务的参数(当前不需要,所以为0); | |||||
| * 3. 初始栈顶地址; | |||||
| * 4. 任务优先级,数值越小优先级越高; | |||||
| * 5. 任务ID,本工程暂时与优先级取相同值; | |||||
| * 6. 栈底地址; | |||||
| * 7. 栈容量,单位是OS_STK元素而不是字节; | |||||
| * 8. 用户扩展指针(当前不用); | |||||
| * 9. 创建选项:允许栈检查并在创建时清零任务栈。 | |||||
| */ | |||||
| os_err = OSTaskCreateExt(AppTaskStart, | os_err = OSTaskCreateExt(AppTaskStart, | ||||
| 0, | 0, | ||||
| &AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u], | &AppTaskStartStk[APP_TASK_START_STK_SIZE - 1u], | ||||
| @@ -151,6 +189,11 @@ int main(void) | |||||
| { | { | ||||
| Error_Handler(); | Error_Handler(); | ||||
| } | } | ||||
| /* | |||||
| * 启动抢占式调度,内核会运行当前最高优先级的就绪任务。 | |||||
| * OSStart()成功后不会返回,后面的裸机while循环不会再被执行。 | |||||
| */ | |||||
| OSStart(); | OSStart(); | ||||
| /* USER CODE END 2 */ | /* USER CODE END 2 */ | ||||
| @@ -190,8 +190,15 @@ void SysTick_Handler(void) | |||||
| /* USER CODE BEGIN SysTick_IRQn 0 */ | /* USER CODE BEGIN SysTick_IRQn 0 */ | ||||
| /* USER CODE END SysTick_IRQn 0 */ | /* USER CODE END SysTick_IRQn 0 */ | ||||
| /* 维持STM32 HAL自己的1ms时基,HAL_GetTick()等接口依赖它。 */ | |||||
| HAL_IncTick(); | HAL_IncTick(); | ||||
| /* USER CODE BEGIN SysTick_IRQn 1 */ | /* USER CODE BEGIN SysTick_IRQn 1 */ | ||||
| /* | |||||
| * HAL_Init()会先于OSInit()启动SysTick,因此必须先判断内核是否已经运行。 | |||||
| * 内核运行后,每个1ms中断调用一次OS节拍处理: | |||||
| * 更新任务延时,并在有更高优先级任务就绪时请求一次PendSV任务切换。 | |||||
| */ | |||||
| if (OSRunning == OS_TRUE) | if (OSRunning == OS_TRUE) | ||||
| { | { | ||||
| OS_CPU_SysTickHandler(); | OS_CPU_SysTickHandler(); | ||||
| @@ -48,7 +48,7 @@ | |||||
| EXTERN __iar_program_start | EXTERN __iar_program_start | ||||
| EXTERN SystemInit | EXTERN SystemInit | ||||
| EXTERN OS_CPU_PendSVHandler | |||||
| EXTERN OS_CPU_PendSVHandler ; uC/OS-II context-switch exception handler | |||||
| PUBLIC __vector_table | PUBLIC __vector_table | ||||
| DATA | DATA | ||||
| @@ -68,7 +68,7 @@ __vector_table | |||||
| DCD SVC_Handler ; SVCall Handler | DCD SVC_Handler ; SVCall Handler | ||||
| DCD DebugMon_Handler ; Debug Monitor Handler | DCD DebugMon_Handler ; Debug Monitor Handler | ||||
| DCD 0 ; Reserved | DCD 0 ; Reserved | ||||
| DCD OS_CPU_PendSVHandler ; uC/OS-II context switch | |||||
| DCD OS_CPU_PendSVHandler ; PendSV is owned by uC/OS-II for task switching | |||||
| DCD SysTick_Handler ; SysTick Handler | DCD SysTick_Handler ; SysTick Handler | ||||
| ; External Interrupts | ; External Interrupts | ||||
| @@ -1,10 +1,18 @@ | |||||
| #ifndef APP_CFG_H | #ifndef APP_CFG_H | ||||
| #define APP_CFG_H | #define APP_CFG_H | ||||
| /* | |||||
| * uC/OS-II优先级数值越小,任务优先级越高。 | |||||
| * 每个任务必须使用不同的优先级;0通常留给最紧急的系统任务。 | |||||
| */ | |||||
| #define APP_TASK_START_PRIO 5u | #define APP_TASK_START_PRIO 5u | ||||
| #define APP_TASK_TEST_PRIO 6u | #define APP_TASK_TEST_PRIO 6u | ||||
| /* | |||||
| * 任务栈大小的单位是OS_STK元素。当前OS_STK为32位, | |||||
| * 所以每个256元素的任务栈实际占用1024字节RAM。 | |||||
| */ | |||||
| #define APP_TASK_START_STK_SIZE 256u | #define APP_TASK_START_STK_SIZE 256u | ||||
| #define APP_TASK_TEST_STK_SIZE 256u | #define APP_TASK_TEST_STK_SIZE 256u | ||||
| #endif | |||||
| #endif | |||||
| @@ -27,9 +27,9 @@ | |||||
| /* ---------------------- MISCELLANEOUS ----------------------- */ | /* ---------------------- MISCELLANEOUS ----------------------- */ | ||||
| #define OS_APP_HOOKS_EN 0u /* Application-defined hooks are called from the uC/OS-II hooks */ | |||||
| #define OS_APP_HOOKS_EN 0u /* 初次移植不使用应用层钩子函数 */ | |||||
| #define OS_ARG_CHK_EN 0u /* Enable (1) or Disable (0) argument checking */ | #define OS_ARG_CHK_EN 0u /* Enable (1) or Disable (0) argument checking */ | ||||
| #define OS_CPU_HOOKS_EN 1u /* uC/OS-II hooks are found in the processor port files */ | |||||
| #define OS_CPU_HOOKS_EN 1u /* 使用Cortex-M4端口提供的CPU钩子函数 */ | |||||
| #define OS_DEBUG_EN 1u /* Enable(1) debug variables */ | #define OS_DEBUG_EN 1u /* Enable(1) debug variables */ | ||||
| @@ -43,12 +43,12 @@ | |||||
| #define OS_MAX_FLAGS 5u /* Max. number of Event Flag Groups in your application */ | #define OS_MAX_FLAGS 5u /* Max. number of Event Flag Groups in your application */ | ||||
| #define OS_MAX_MEM_PART 5u /* Max. number of memory partitions */ | #define OS_MAX_MEM_PART 5u /* Max. number of memory partitions */ | ||||
| #define OS_MAX_QS 4u /* Max. number of queue control blocks in your application */ | #define OS_MAX_QS 4u /* Max. number of queue control blocks in your application */ | ||||
| #define OS_MAX_TASKS 10u /* Max. number of tasks in your application, MUST be >= 2 */ | |||||
| #define OS_MAX_TASKS 10u /* 应用最多可创建10个任务(不包括内核自动创建的系统任务) */ | |||||
| #define OS_SCHED_LOCK_EN 1u /* Include code for OSSchedLock() and OSSchedUnlock() */ | #define OS_SCHED_LOCK_EN 1u /* Include code for OSSchedLock() and OSSchedUnlock() */ | ||||
| #define OS_TICK_STEP_EN 1u /* Enable tick stepping feature for uC/OS-View */ | #define OS_TICK_STEP_EN 1u /* Enable tick stepping feature for uC/OS-View */ | ||||
| #define OS_TICKS_PER_SEC 1000u /* Set the number of ticks in one second */ | |||||
| #define OS_TICKS_PER_SEC 1000u /* 每秒1000个节拍,即每个系统节拍为1ms */ | |||||
| #define OS_TLS_TBL_SIZE 0u /* Size of Thread-Local Storage Table */ | #define OS_TLS_TBL_SIZE 0u /* Size of Thread-Local Storage Table */ | ||||
| @@ -68,8 +68,8 @@ | |||||
| #define OS_TASK_PROFILE_EN 1u /* Include variables in OS_TCB for profiling */ | #define OS_TASK_PROFILE_EN 1u /* Include variables in OS_TCB for profiling */ | ||||
| #define OS_TASK_QUERY_EN 1u /* Include code for OSTaskQuery() */ | #define OS_TASK_QUERY_EN 1u /* Include code for OSTaskQuery() */ | ||||
| #define OS_TASK_REG_TBL_SIZE 1u /* Size of task variables array (#of INT32U entries) */ | #define OS_TASK_REG_TBL_SIZE 1u /* Size of task variables array (#of INT32U entries) */ | ||||
| #define OS_TASK_STAT_EN 0u /* Enable (1) or Disable(0) the statistics task */ | |||||
| #define OS_TASK_STAT_STK_CHK_EN 0u /* Check task stacks from statistic task */ | |||||
| #define OS_TASK_STAT_EN 0u /* 初次移植关闭CPU使用率统计任务 */ | |||||
| #define OS_TASK_STAT_STK_CHK_EN 0u /* 统计任务关闭时同时关闭它的周期栈检查 */ | |||||
| #define OS_TASK_SUSPEND_EN 1u /* Include code for OSTaskSuspend() and OSTaskResume() */ | #define OS_TASK_SUSPEND_EN 1u /* Include code for OSTaskSuspend() and OSTaskResume() */ | ||||
| #define OS_TASK_SW_HOOK_EN 1u /* Include code for OSTaskSwHook() */ | #define OS_TASK_SW_HOOK_EN 1u /* Include code for OSTaskSwHook() */ | ||||