在STM32F103工程上新增uCOS-II的過程
阿新 • • 發佈:2019-02-18
開發環境:Keil uVision5
去官網下載:Micrium_STM32xxx_uCOS-II.exe
1.建立uCOS-II資料夾
2.將以下檔案複製到uCOS-II資料夾(不建立子資料夾)
Micrium\Software\uCOS-II\Source\* (1個h檔案,10個c檔案)
Micrium\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\RealView\* (1個h檔案,2個c檔案,1個asm檔案)
Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\OS-Probe\os_cfg.h
(共計3個頭檔案,12個c檔案和1個asm檔案)
3.在Keil工程中新建分組uCOS-II,將12個c檔案和1個asm檔案新增到該分組中
4.開啟os_cfg.h,將OS_APP_HOOKS_EN的值改為0
5.開啟ucos_ii.h檔案,將#include <app_cfg.h>註釋掉
6.開啟STM32微控制器的啟動檔案(如RTE\Device\STM32F103ZE\startup_stm32f10x_hd.s),將PendSV_Handler替換為OS_CPU_PendSVHandler,再將SysTick_Handler替換為OS_CPU_SysTickHandler(各三處)
7.把uCOS-II資料夾新增到專案屬性的C/C++選項卡下的Include Paths文字框內,並在Target選項卡中勾選上Use MicroLIB(供printf使用)
8.編寫main.c
#include <stdio.h> #include <stm32f10x.h> #include <ucos_ii.h> // 必須定義兩個棧變數 static OS_STK main_stack[128]; static OS_STK my_stack[64]; // 訊號量 static OS_EVENT *my_sem; /* 供printf使用 */ int fputc(int ch, FILE *fp) { if (fp == stdout) { if (ch == '\n') { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, '\r'); } while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, ch); } return ch; } /* 這個函式供作業系統使用, 必須定義 */ INT32U OS_CPU_SysTickClkFreq(void) { return SystemCoreClock; } /* 示例任務: 按下PA0按鍵後輸出一段文字 */ void test(void *arg) { uint16_t value = 0; while (1) { if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET) { OSTimeDlyHMSM(0, 0, 0, 15); if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET) { printf("[%d] STM32F103ZE\n", value); value++; while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == SET) OSTimeDlyHMSM(0, 0, 0, 15); } } OSTimeDlyHMSM(0, 0, 0, 30); } } /* 主任務 */ void main_task(void *arg) { uint8_t bit, err; GPIO_InitTypeDef gpio; NVIC_InitTypeDef nvic; TIM_TimeBaseInitTypeDef tim; USART_InitTypeDef usart; OS_CPU_SysTickInit(); // 必須呼叫這個函式 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_USART1, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); gpio.GPIO_Mode = GPIO_Mode_IPD; gpio.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA, &gpio); // 可以建立新任務 OSTaskCreate(test, NULL, &my_stack[63], 1); gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; gpio.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio); gpio.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Pin = GPIO_Pin_9; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &gpio); USART_StructInit(&usart); usart.USART_BaudRate = 115200; USART_Init(USART1, &usart); USART_Cmd(USART1, ENABLE); printf("Started!\n"); TIM_TimeBaseStructInit(&tim); tim.TIM_Period = 9999; tim.TIM_Prescaler = 7199; TIM_TimeBaseInit(TIM1, &tim); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, ENABLE); my_sem = OSSemCreate(0); nvic.NVIC_IRQChannel = TIM1_UP_IRQn; nvic.NVIC_IRQChannelCmd = ENABLE; nvic.NVIC_IRQChannelPreemptionPriority = 0; nvic.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&nvic); while (1) { bit = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4); GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)!bit); GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)bit); OSSemPend(my_sem, 0, &err); // 等待訊號量 } } int main(void) { OSInit(); OSTaskCreate(main_task, NULL, &main_stack[127], 0); OSStart(); } /* 中斷處理函式的寫法 */ void TIM1_UP_IRQHandler(void) { OS_CPU_SR cpu_sr; OS_ENTER_CRITICAL(); OSIntNesting++; OS_EXIT_CRITICAL(); /** 中斷處理開始 **/ TIM_ClearITPendingBit(TIM1, TIM_IT_Update); OSSemPost(my_sem); // 喚醒主任務 /** 中斷處理結束 **/ OSIntExit(); }