本帖最后由 xld0932 于 2023-2-21 10:01 编辑
#申请原创# @21小跑堂
做嵌入式(MCU)软件开发的小伙伴,对IAR的EWARM集成开发环境都不陌生,我之前都是使用的IAR EWARM 8.32版本的,使用也一直很稳定,有好长时间没有去关注和更新新的IAR EWARM版本了……最近突然心血来潮,更新到IAR EWARM 9.30.1版本,发现之前的项目工程突然都不灵了!!!咋回事呢???
回退到IAR EWARM 8.32版本,原先的项目工程依旧可以正常运行,但切换到IAR EWARM 9.30.1版本后,程序就卡在一半不执行了;经过一点一点的分析(在线调试、单步运行)后,发现竟然卡在了最常用的printf函数这里了……
对于要实现printf函数的功能,除了在工程配置时,需要增加_DLIB_FILE_DESCRIPTOR这个宏定义之外还需要重载一下fputc这个底层函数,当然也要初始化对应的打印串口参数哈:
/***********************************************************************************************************************
* [url=home.php?mod=space&uid=247401]@brief[/url] Initialize console for printf
* [url=home.php?mod=space&uid=536309]@NOTE[/url] none
* @param Baudrate : UART2 communication baudrate
* @retval none
*********************************************************************************************************************/
void PLATFORM_InitConsole(uint32_t Baudrate)
{
GPIO_InitTypeDef GPIO_InitStruct;
UART_InitTypeDef UART_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1ENR_UART2, ENABLE);
UART_StructInit(&UART_InitStruct);
UART_InitStruct.BaudRate = Baudrate;
UART_InitStruct.WordLength = UART_WordLength_8b;
UART_InitStruct.StopBits = UART_StopBits_1;
UART_InitStruct.Parity = UART_Parity_No;
UART_InitStruct.HWFlowControl = UART_HWFlowControl_None;
UART_InitStruct.Mode = UART_Mode_Tx;
UART_Init(UART2, &UART_InitStruct);
UART_Cmd(UART2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/***********************************************************************************************************************
* @brief Redefine fputc function
* @note For printf
* @param ch
* @param f
* @retval ch
*********************************************************************************************************************/
int fputc(int ch, FILE *f)
{
UART_SendData(UART2, (uint8_t)ch);
while (RESET == UART_GetFlagStatus(UART2, UART_FLAG_TXEPT))
{
}
return (ch);
}
代码一丝丝都没修改过,不可能会有问题哈……
最后还是查看IAR的帮助文档,发现从IAR EWARM 9.3版本之后,要实现printf函数不是重载fputc这个函数了,而是需要重载__write这个函数,通过帮助文档里给出的示例代码作参考,尝试了一下:
/* Files include */
#include <stddef.h>
#include <LowLevelIOInterface.h>
/***********************************************************************************************************************
* @brief redefine __write function
* @note for printf
* @param handle
* @param *buf
* @param bufSize
* @retval nChars
*********************************************************************************************************************/
size_t __write(int handle, const unsigned char *buf, size_t bufSize)
{
size_t nChars = 0;
/* Check for the command to flush all handles */
if (-1 == handle)
{
return (0);
}
/* Check for stdout and stderr (only necessary if FILE descriptors are enabled.) */
if ((_LLIO_STDOUT != handle) && (_LLIO_STDERR != handle))
{
return (-1);
}
for (/* Empty */; bufSize > 0; --bufSize)
{
UART_SendData(UART2, *buf);
while (RESET == UART_GetFlagStatus(UART2, UART_FLAG_TXEPT))
{
}
++buf;
++nChars;
}
return (nChars);
}
此时再使用IAR EWARM 9.30.1版本软件进行编译、下载后,项目代码终于可以正常运行了……这个printf功能卡脖子有问题终于解决了!!!
那在代码中我如何判断当前IAR的版本是8.32还是9.30呢?在IAR编译器中提供了这样两个宏,一个是__ICCARM__,这个表示当前使用的IAR EWARM编译器环境,另外一个是__VER__,它可以判断当前编译器的软件版本号,这样我们就可以通过这两个宏来判断,我们在实现printf函数时,是需要重载fputc函数还是__write函数了,做到项目工程的兼容,不会再出现上述问题导致的MCU卡住了!
|
心思缜密,条分缕析,剖析根源,解决难题