RT-thread近年来频繁出现在嵌入式开发者的视野中,他们的大力推广以及技术支持受到了很多人的广泛支持与关注。本人在去年(还是一个职业小白)也参加了rt的教学实验,体验过env工具的方便以及如何结合stm32cubemx实现快速建立rt工程。不过,rt官方主要打造针对一些较高资源的ic的开发生态环境,比如stm32f407或者stm32f103zet6等高ram和高rom的ic(品牌开发板标配)。但是实际工作中,对于我们公司开发的ic并不需要很大资源的ic去开发,比如物联网项目我们往往是只用stm32f030或者很高资源用的stm32f103RB等,其最大rom保持在128k以下,甚至更低,而ram更加是只需要20k。可是基于rt的开发生态通过env工具建立工程时,当移植完部分组件之后还未开发应用时便几乎超过了20k的ram了。因此往往我们还是拿rtthread的nano精简版本进行开发。原因是其配合stm32cubemx开发太方便了。
硬件:nucleo-g070RB开发板
该开发板板载了stlink烧录调试器,因此我们只需要准备一个miniusb数据线即可实现电脑pc和开发板的调试对接。又因为其stlinkv2-1版本又支持扩展串口功能,这个开发板实现了stlink拓展串口连接到stm32g070rb主控芯片的uart2串口的引脚。因此我们不仅不需要自备烧录器,也不需要自备ch340等串口硬件工具,只需要直接准备一根micro数据线完成烧录、调试及串口通讯。其他具体资源介绍可参考以下链接:nucleo-g070rb开发板数据手册
打开cube新建工程,本人选择stm32f070rb型号
工程预览
时钟源选择,外部时钟源本人全部失能,准备启用内部时钟源配置。
串口异步配置,默认配置。
添加RT软件包,找到软件软件包选项点击,然后在选择组件
本人已经下载好了rt组件,勾选其组件,点击ok退出。
再到NVIC配置取消掉硬件错误中断,因为rt组件会帮你配置,不消掉iar工程编译会报错,也可以iar工程注释掉其中断。
时钟树配置,内部高速时钟源,选择最快的时钟频率64Mhz,不考虑低功耗。
工程管理,添加工程名
代码生成配置,勾选如下图所示的箭头,这样驱动文件更加模块化分配到各个c文件中。
预设置,把两个初始化去掉,这样main里就不会生成这两个初始化调用,因为到时rt配置的时候会重复,不勾的话最终在工程还是要删除掉,否则程序功能不正常。
点击生成工程GENEEATE CODE,生成IAR工程。
打开open project,即可开始配置IAR工程。
void rt_hw_console_output(const char *str) {
rt_size_t i = 0, size = 0;
char a = '\r';
__HAL_UNLOCK(&huartx);
size = rt_strlen(str);
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n') {
HAL_UART_Transmit(&huartx, (uint8_t *)&a, 1, 1);
}
HAL_UART_Transmit(&huartx, (uint8_t *)(str + i), 1, 1);
}
}
char rt_hw_console_getchar(void) { char ch ; //rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER); //接 收 信 号 量 //ch = huartx.Instance->DR & 0xff; //读 取 数 据 if(rt_mq_recv(&shell_rx_mq, &ch,1, RT_WAITING_FOREVER) == RT_EOK) { } return ch; } void USARTx_IRQHandler(void) { int ch = -1; if((__HAL_UART_GET_FLAG(&huartx, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&(huartx), UART_IT_RXNE) != RESET)) //接 收 中 断 { __HAL_UART_CLEAR_FLAG(&(huartx), UART_FLAG_RXNE); //清 除 中 断 __HAL_UART_CLEAR_PEFLAG(&(huartx)) ; #if defined(STM32G0xx_HAL_H) ch = huartx.Instance->RDR & 0xff; //读 取 数 据 #elif defined(__STM32F1xx_HAL_H) ch = huartx.Instance->DR & 0xff; //读 取 数 据 #else #error no sure ic type #endif rt_mq_send(&shell_rx_mq, &ch,1); } __HAL_UART_CLEAR_PEFLAG(&huartx) ; }
void lc_shell_uart_init(void) {
//rt_sem_init(&(shell_rx_sem), "shell_rx", 0, 0);
rt_mq_init(&shell_rx_mq,
"shell_rx",
shell_rx_buf, /* 内存池指向 shell_rx_buf */
1, /* 每个消息的大小是 1 字节 */
sizeof(shell_rx_buf), /* 内存池的大小是 shell_rx_buf 的大小 */
RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
MX_USART2_UART_Init();
}
void MX_USART2_UART_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = DEBUG_TX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DEBUG_TX_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = DEBUG_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DEBUG_RX_GPIO_Port, &GPIO_InitStruct);
huartx.Instance = USART2;
huartx.Init.BaudRate = 115200;
huartx.Init.WordLength = UART_WORDLENGTH_8B;
huartx.Init.StopBits = UART_STOPBITS_1;
huartx.Init.Parity = UART_PARITY_NONE;
huartx.Init.Mode = UART_MODE_TX_RX;
huartx.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huartx.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huartx) != HAL_OK)
{
// Error_Handler();
}
__HAL_UART_ENABLE_IT(&huartx, UART_IT_RXNE);//中断使能
HAL_NVIC_EnableIRQ(USART2_IRQn);
HAL_NVIC_SetPriority(USART2_IRQn, 3, 3);
}
执行程序整个移植工作总结