本帖最后由 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卡住了!

|