发新帖本帖赏金 20.00元(功能说明)我要提问
返回列表
打印
[MM32软件]

IAR使用printf函数后MCU挂掉了,看我如何解决的^^

[复制链接]
1549|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xld0932|  楼主 | 2023-2-21 09:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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卡住了!


使用特权

评论回复

打赏榜单

21小跑堂 打赏了 20.00 元 2023-02-24
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
21小跑堂 2023-2-24 10:29 回复TA
心思缜密,条分缕析,剖析根源,解决难题 
沙发
yangxiaor520| | 2023-2-22 07:38 | 只看该作者
不错的经验分享,点个赞。

使用特权

评论回复
板凳
EPTmachine| | 2023-2-24 14:03 | 只看该作者
写的很好,以后可以少走一个坑

使用特权

评论回复
地板
Innercourage| | 2023-2-27 08:55 | 只看该作者
不错的经验分享,点个赞

使用特权

评论回复
5
zchong| | 2023-2-27 12:34 | 只看该作者
也中招了,不晓得iar为啥要改动这个,

使用特权

评论回复
6
tpgf| | 2023-3-2 09:25 | 只看该作者
为什么高版本的反而不能默认支持这个函数呢

使用特权

评论回复
7
qcliu| | 2023-3-2 09:48 | 只看该作者
有可能也是习惯问题 不过确实更加喜欢使用低版本的

使用特权

评论回复
8
drer| | 2023-3-2 10:10 | 只看该作者
大家一直用的很习惯的函数重载 为什么版本更新后就更改了函数了呢

使用特权

评论回复
9
coshi| | 2023-3-2 10:47 | 只看该作者
看来每个版本更改之后我们有必要看一下相关说明文档啊

使用特权

评论回复
10
kxsi| | 2023-3-2 11:10 | 只看该作者
我比较发愁的就是 总不能我换版本的时候还都要详细对比一下区别啊

使用特权

评论回复
11
wiba| | 2023-3-2 11:23 | 只看该作者
kxsi 发表于 2023-3-2 11:10
我比较发愁的就是 总不能我换版本的时候还都要详细对比一下区别啊

这确实是一个问题 好在这个坑楼主已经填上了

使用特权

评论回复
12
10299823| | 2023-3-2 16:03 | 只看该作者
重新写fput不行吗?              

使用特权

评论回复
13
everyrobin| | 2023-3-2 16:12 | 只看该作者
IAR和keil的printf不一样 。

使用特权

评论回复
14
geraldbetty| | 2023-3-4 21:53 | 只看该作者
串口的配置的吗?              

使用特权

评论回复
15
deliahouse887| | 2023-3-7 20:18 | 只看该作者
单片机怎么会挂掉的?              

使用特权

评论回复
16
mattlincoln| | 2023-3-7 20:37 | 只看该作者
串口的配置的吗?              

使用特权

评论回复
17
Undshing| | 2023-3-9 18:38 | 只看该作者
可能高版本;有更好的函数替换了

使用特权

评论回复
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:上海灵动微电子股份有限公司资深现场应用工程师
简介:诚信·承诺·创新·合作

70

主题

3001

帖子

31

粉丝