总览
本文基于STM32F103C8T6,详细讲述华为LiteOS的移植过程。开发工具是MDK5。LiteOS官方已经适配过cortex M系列内核的单片机,因此移植过程非常简单。
LiteOS有两种移植方案:OS接管中断和非接管中断方式。接管中断的方式,是由LiteOS创建很管理中断,需要修改stm32启动文件,移植比较复杂。STM32的中断管理做的很好,用不着由LiteOS管理中断,所以我们下边的移植方案,都是非接管中断的方式的。中断的使用,跟在裸机工程时是一样的。
在target_config.h 中将 LOSCFG_PLATFORM_HWI 宏定义为 NO,即为不接管中断方式。该值默认为NO 。
移植的主要步骤如下:
1、添加内核文件
2、配置头文件
3、移除systick和pendsv中断
4、修改target_config.h
5、重定向printf函数(一般在裸机工程中就会实现)
说明:内核运行过程中会通过串口打印一些错误信息。如果日志功能开启、而又没有重定向printf函数的话,则会导致日志打印出错,程序异常卡死。之前我就是没有重定向printf函数,结果出了莫名其妙的问题,程序异常卡死在创建任务的地方。
下边我们通过新建一个裸机工程,一步步讲解如何进行移植。以下是详细过程。
一、创建裸机工程
我们这次使用的是一个STM32F103C8T6的最小系统板,板载有三个LED、一个串口。LED连接引脚为(PB5PB6PB7),低电平点亮;串口为USART1(PA9,PA10),采用DMA+空闲中断的方式接收数据。我们利用STM32CubeMX来生成裸机工程(STM32CubeMX的使用本文不详细描述),设置如下:
1、引脚配置
- 配置PB5PB6PB7为推挽输出方式;
- 配置PA9PA10为USART1复用功能;
- 配置PA13为SWDIO功能,PA14为SWCLK功能(下载及调试)
- 使能串行调试功能
2、时钟配置
3、串口配置
4、生成代码
勾选生成对应外设驱动的‘.c/.h’文件,生成代码。
打开工程,加入LED开关状态的宏定义和串口空闲中断接收的代码,具体如下(当然,如果你不使用DMA+空闲中断的方式,也可以不进行下边2中的修改,但是一定要重定向printf函数):
1、在main.h中加入LED宏定义代码。
1 #define LED1_ON() HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_RESET)2 #define LED1_OFF() HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_SET)3 4 #define LED2_ON() HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_RESET)5 #define LED2_OFF() HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_SET)6 7 #define LED3_ON() HAL_GPIO_WritePin(GPIOB, LED3_Pin, GPIO_PIN_RESET)8 #define LED3_OFF() HAL_GPIO_WritePin(GPIOB, LED3_Pin, GPIO_PIN_SET)2、实现串口空闲中断接收
在usart.h中加入如下代码:
1 #define UART1_BUFF_SIZE 256 //串口接收缓存区长度 2 typedef struct 3 { 4 uint8_t RxFlag; //空闲接收标记 5 uint16_t RxLen; //接收长度 6 uint8_t *RxBuff; //DMA接收缓存 7 }USART_RECEIVETYPE; 8 extern USART_RECEIVETYPE Uart1Rx; 9 void USART1_ReceiveIDLE(void);10 void UART_SendData(USART_TypeDef * Uart,uint8_t *buff,uint16_t size);11 在usart.c中加入如下代码12 static uint8_t Uar1tRxBuff[UART1_BUFF_SIZE+1]; //定义串口接收buffer13 USART_RECEIVETYPE Uart1Rx = {14 .RxBuff = Uar1tRxBuff,15 };16 17 void USART1_ReceiveIDLE(void) 18 { 19 uint32_t temp; 20 if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)) 21 {22 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE); 23 temp = huart1.Instance->SR;24 temp = huart1.Instance->DR;25 HAL_UART_DMAStop(&huart1); 26 temp = huart1.hdmarx->Instance->CNDTR; 27 Uart1Rx.RxLen = UART1_BUFF_SIZE - temp; 28 Uart1Rx.RxFlag=1; 29 Uart1Rx.RxBuff[Uart1Rx.RxLen] = 0;30 HAL_UART_Receive_DMA(&huart1,Uart1Rx.RxBuff,UART1_BUFF_SIZE); 31 } 32 }33 void UART_SendByte(USART_TypeDef * Uart,uint8_t data)34 { 35 Uart->DR = data;36 while((Uart->SR&UART_FLAG_TXE)==0);37 while((Uart->SR&UART_FLAG_TC)==0); 38 }39 void UART_SendData(USART_TypeDef * Uart,uint8_t *buff,uint16_t size)40 {41 while(size--)42 {43 Uart->DR = *(buff++);44 while((Uart->SR&UART_FLAG_TXE)==0);45 }46 while((Uart->SR&UART_FLAG_TC)==0); 47 }48 ///重定向c库函数printf到USART149 int fputc(int ch, FILE *f)50 {51 /* 发送一个字节数据到USART1 */52 UART_SendByte(USART1, (uint8_t) ch);53 return (ch);54 }55 56 ///重定向c库函数scanf到USART157 int fgetc(FILE *f)58 {59 /* 等待串口1输入数据 */60 while((USART1->SR&UART_FLAG_RXNE)==0);61 return (int)USART1->DR&0xff;62 }
修改void MX_USART1_UART_Init(void),在最后加入以下代码:
1 //add for DMA.Idle interrupt2 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE); 3 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TC); 4 HAL_UART_Receive_DMA(&huart1, Uart1Rx.RxBuff, UART1_BUFF_SIZE); //开启DMA接收 5 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能空闲中断在stm32f1xx_it.c中声明USART1_ReceiveIDLE,并在串口中断中调用该函数:
1 void USART1_ReceiveIDLE(void); 2 3 void USART1_IRQHandler(void) 4 { 5 /* USER CODE BEGIN USART1_IRQn 0 */ 6 USART1_ReceiveIDLE(); 7 /* USER CODE END USART1_IRQn 0 */ 8 HAL_UART_IRQHandler(&huart1); 9 /* USER CODE BEGIN USART1_IRQn 1 */ 10 11 /* USER CODE END USART1_IRQn 1 */ 12 }
3、在main.c的main中添加代码验证裸机工程
1 while (1) 2 { 3 /* USER CODE END WHILE */ 4 5 /* USER CODE BEGIN 3 */ 6 LED1_ON(); 7 LED2_ON(); 8 LED3_ON(); 9 HAL_Delay(300); 10 LED1_OFF(); 11 LED2_OFF(); 12 LED3_OFF(); 13 HAL_Delay(300); 14 printf("This is the uart test!rn"); 15 if(Uart1Rx.RxFlag){ 16 Uart1Rx.RxFlag = 0; 17 UART_SendData(USART1,Uart1Rx.RxBuff,Uart1Rx.RxLen); 18 } 19 }
编译下载代码,程序正常运行,LED闪烁,同时打印字符串。
经过上述操作,我们已经完成了裸机工程的准备工作。
二、内核移植
1、下载LiteOS
注:LiteOS 最新特性都存放在 develop 分支中,建议取该分支代码进行学习。本文的代码即为 develop分支代码。
点击链接进入LiteOS代码仓库首页,切换至develop分支,点击右侧“Clone or download”按钮,选择Download ZIP,下载代码,如下图所示:
LiteOS内核代码目录结构如下图所示:

总览
本文基于STM32F103C8T6,详细讲述华为LiteOS的移植过程。开发工具是MDK5。LiteOS官方已经适配过cortex M系列内核的单片机,因此移植过程非常简单。
LiteOS有两种移植方案:OS接管中断和非接管中断方式。接管中断的方式,是由LiteOS创建很管理中断,需要修改stm32启动文件,移植比较复杂。STM32的中断管理做的很好,用不着由LiteOS管理中断,所以我们下边的移植方案,都是非接管中断的方式的。中断的使用,跟在裸机工程时是一样的。
在target_config.h 中将 LOSCFG_PLATFORM_HWI 宏定义为 NO,即为不接管中断方式。该值默认为NO 。
移植的主要步骤如下:
1、添加内核文件
2、配置头文件
3、移除systick和pendsv中断
4、修改target_config.h
5、重定向printf函数(一般在裸机工程中就会实现)
说明:内核运行过程中会通过串口打印一些错误信息。如果日志功能开启、而又没有重定向printf函数的话,则会导致日志打印出错,程序异常卡死。之前我就是没有重定向printf函数,结果出了莫名其妙的问题,程序异常卡死在创建任务的地方。
下边我们通过新建一个裸机工程,一步步讲解如何进行移植。以下是详细过程。
一、创建裸机工程
我们这次使用的是一个STM32F103C8T6的最小系统板,板载有三个LED、一个串口。LED连接引脚为(PB5PB6PB7),低电平点亮;串口为USART1(PA9,PA10),采用DMA+空闲中断的方式接收数据。我们利用STM32CubeMX来生成裸机工程(STM32CubeMX的使用本文不详细描述),设置如下:
1、引脚配置
- 配置PB5PB6PB7为推挽输出方式;
- 配置PA9PA10为USART1复用功能;
- 配置PA13为SWDIO功能,PA14为SWCLK功能(下载及调试)
- 使能串行调试功能
2、时钟配置
3、串口配置
4、生成代码
勾选生成对应外设驱动的‘.c/.h’文件,生成代码。
打开工程,加入LED开关状态的宏定义和串口空闲中断接收的代码,具体如下(当然,如果你不使用DMA+空闲中断的方式,也可以不进行下边2中的修改,但是一定要重定向printf函数):
1、在main.h中加入LED宏定义代码。
1 #define LED1_ON() HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_RESET)2 #define LED1_OFF() HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_SET)3 4 #define LED2_ON() HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_RESET)5 #define LED2_OFF() HAL_GPIO_WritePin(GPIOB, LED2_Pin, GPIO_PIN_SET)6 7 #define LED3_ON() HAL_GPIO_WritePin(GPIOB, LED3_Pin, GPIO_PIN_RESET)8 #define LED3_OFF() HAL_GPIO_WritePin(GPIOB, LED3_Pin, GPIO_PIN_SET)2、实现串口空闲中断接收
在usart.h中加入如下代码:
1 #define UART1_BUFF_SIZE 256 //串口接收缓存区长度 2 typedef struct 3 { 4 uint8_t RxFlag; //空闲接收标记 5 uint16_t RxLen; //接收长度 6 uint8_t *RxBuff; //DMA接收缓存 7 }USART_RECEIVETYPE; 8 extern USART_RECEIVETYPE Uart1Rx; 9 void USART1_ReceiveIDLE(void);10 void UART_SendData(USART_TypeDef * Uart,uint8_t *buff,uint16_t size);11 在usart.c中加入如下代码12 static uint8_t Uar1tRxBuff[UART1_BUFF_SIZE+1]; //定义串口接收buffer13 USART_RECEIVETYPE Uart1Rx = {14 .RxBuff = Uar1tRxBuff,15 };16 17 void USART1_ReceiveIDLE(void) 18 { 19 uint32_t temp; 20 if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)) 21 {22 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE); 23 temp = huart1.Instance->SR;24 temp = huart1.Instance->DR;25 HAL_UART_DMAStop(&huart1); 26 temp = huart1.hdmarx->Instance->CNDTR; 27 Uart1Rx.RxLen = UART1_BUFF_SIZE - temp; 28 Uart1Rx.RxFlag=1; 29 Uart1Rx.RxBuff[Uart1Rx.RxLen] = 0;30 HAL_UART_Receive_DMA(&huart1,Uart1Rx.RxBuff,UART1_BUFF_SIZE); 31 } 32 }33 void UART_SendByte(USART_TypeDef * Uart,uint8_t data)34 { 35 Uart->DR = data;36 while((Uart->SR&UART_FLAG_TXE)==0);37 while((Uart->SR&UART_FLAG_TC)==0); 38 }39 void UART_SendData(USART_TypeDef * Uart,uint8_t *buff,uint16_t size)40 {41 while(size--)42 {43 Uart->DR = *(buff++);44 while((Uart->SR&UART_FLAG_TXE)==0);45 }46 while((Uart->SR&UART_FLAG_TC)==0); 47 }48 ///重定向c库函数printf到USART149 int fputc(int ch, FILE *f)50 {51 /* 发送一个字节数据到USART1 */52 UART_SendByte(USART1, (uint8_t) ch);53 return (ch);54 }55 56 ///重定向c库函数scanf到USART157 int fgetc(FILE *f)58 {59 /* 等待串口1输入数据 */60 while((USART1->SR&UART_FLAG_RXNE)==0);61 return (int)USART1->DR&0xff;62 }
修改void MX_USART1_UART_Init(void),在最后加入以下代码:
1 //add for DMA.Idle interrupt2 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE); 3 __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TC); 4 HAL_UART_Receive_DMA(&huart1, Uart1Rx.RxBuff, UART1_BUFF_SIZE); //开启DMA接收 5 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能空闲中断在stm32f1xx_it.c中声明USART1_ReceiveIDLE,并在串口中断中调用该函数:
1 void USART1_ReceiveIDLE(void); 2 3 void USART1_IRQHandler(void) 4 { 5 /* USER CODE BEGIN USART1_IRQn 0 */ 6 USART1_ReceiveIDLE(); 7 /* USER CODE END USART1_IRQn 0 */ 8 HAL_UART_IRQHandler(&huart1); 9 /* USER CODE BEGIN USART1_IRQn 1 */ 10 11 /* USER CODE END USART1_IRQn 1 */ 12 }
3、在main.c的main中添加代码验证裸机工程
1 while (1) 2 { 3 /* USER CODE END WHILE */ 4 5 /* USER CODE BEGIN 3 */ 6 LED1_ON(); 7 LED2_ON(); 8 LED3_ON(); 9 HAL_Delay(300); 10 LED1_OFF(); 11 LED2_OFF(); 12 LED3_OFF(); 13 HAL_Delay(300); 14 printf("This is the uart test!rn"); 15 if(Uart1Rx.RxFlag){ 16 Uart1Rx.RxFlag = 0; 17 UART_SendData(USART1,Uart1Rx.RxBuff,Uart1Rx.RxLen); 18 } 19 }
编译下载代码,程序正常运行,LED闪烁,同时打印字符串。
经过上述操作,我们已经完成了裸机工程的准备工作。
二、内核移植
1、下载LiteOS
注:LiteOS 最新特性都存放在 develop 分支中,建议取该分支代码进行学习。本文的代码即为 develop分支代码。
点击链接进入LiteOS代码仓库首页,切换至develop分支,点击右侧“Clone or download”按钮,选择Download ZIP,下载代码,如下图所示:
LiteOS内核代码目录结构如下图所示:

举报