最近使用RT-Thread Studio对之前在IAR上写的rtthread工程进行了重写,用RT-Thread Studio以STM32F413ZH芯片为硬件平台生成了基于rtthread 4.1.1的工程,调试时发现rtthread能够找到串口5设备并且能正常打开,但串口5发送代码执行正常但串口引脚没有数据输出的情况。
刚接触rtthread驱动框架,一开始以为是框架问题,因为之前遇到过用rtthread studio生成的spi sufd代码并不执行其设定框架的问题,于是对drv_usart.c代码进行检查。检查完毕后发现框架结构问题不大,实在找不到原因,考虑可能是硬件配置问题,于是开始检查具体的配置代码。
经检查,该工程在配置串口5时,默认配置的引脚复用是AF8,查看用户手册可知,该芯片在AF8复用模式下串口5所使用的引脚为TX->PC12、RX->PD2,而我的工程的串口5使用的引脚是PB12、PB13,对应的是AF11,因此通信失败。
问题代码在drv_uart.c的stm32_gpio_configure函数中,其与引脚复用有关的代码为:
#define GPIO_AF7 ((uint8_t)0x07)
#define GPIO_AF8 ((uint8_t)0x08)
/* uart1-3 -> AF7, uart4-8 -> AF8 */
if (uart_num <= 3)
{
GPIO_InitStruct.Alternate = GPIO_AF7;
}
else
{
GPIO_InitStruct.Alternate = GPIO_AF8;
}
可知其默认将串口4~8都采用AF8复用模式。这里吐槽一下,虽然配置串口时检查引脚复用是嵌入式程序员的基本操作,但对于刚接触RT的程序员来讲,有这样的设置却又没有在board.h文件中提示(因为board.h中提示了串口配置方法),其实不大友好。
上文已经知道,AF8的复用设置与本项目中使用PB12、PB13作为uart5引脚这一需求相矛盾,因此修改上述代码为:
#define GPIO_AF7 ((uint8_t)0x07)
#define GPIO_AF8 ((uint8_t)0x08)
#define GPIO_AF11 ((uint8_t)0x0B)
/* uart1-3 -> AF7, uart4-8 -> AF8 */
if (uart_num <= 3)
{
GPIO_InitStruct.Alternate = GPIO_AF7;
}
else if(uart_num <= 8 && uart_num != 5)
{
GPIO_InitStruct.Alternate = GPIO_AF8;
}
else
{
GPIO_InitStruct.Alternate = GPIO_AF11;
}
修改后问题解决。
案例总结:rtthread在一些外设的配置过程中帮我们做了很多工作,但无论怎样都无法彻底屏蔽不同硬件设计上必然存在的特异性,因此由RTThread Studio生成的代码在本项目中出现了串口5无法通信的问题。
如果在使用rtthread的过程中出现代码编译通过但某硬件无法使用的情况,应该保持硬件思维,首先向外设配置方面去考虑,如果硬件寄存器数值都正常而外设工作异常,此时再考虑软件框架问题不迟。
另外,该芯片支持串口9和串口10,但由rtthread studio生成的代码缺少对这两个串口的支持,要使用的话需要修改很多东西。再者,上述stm32_gpio_configure函数中对串口号的检查方式有缺陷:
/* get tx/rx pin index */
uart_num = config->name[4] - '0';
该写法只支持串口号小于10的情况,如果要使用串口10,可以改为:
/* get tx/rx pin index */
sscanf(strstr(config->name, "art"), "art%d", &uart_num);
最后,由rtthread studio针对STM32F413ZH生成的工程,已知0.2.2和0.2.3版的芯片支持包对串口7的DMA配置有问题,有使用者请检查dma_config.h中的有关配置。