【问题标题】:STM32 printf and RTCSTM32 printf 和 RTC
【发布时间】:2011-04-24 11:42:06
【问题描述】:

* 更新 *

这是我发现的。每当我在那里拥有该功能时,它实际上不会使代码锁定。它实际上会使读取 RTC I²C 函数的执行速度非常慢,但代码仍然可以正常运行,但是每次读取 RTC 时我都必须等待很长时间才能通过。

因此,RTC 有一个警报中断,这触发了 ISR 内的其他 I²C 交互,因此看起来它试图同时进行两个 I²C 通信,因此减慢了进程。我删除了 ISR 中的功能,它现在可以工作了。我会继续调查的。


我在使用 IAR 5.40 对 STM32F103 微控制器进行编程时遇到了这个问题。我有这个函数,如果我尝试 printf 一个局部变量,它会导致代码在到达相关函数之前冻结在另一个点。

这可能是什么原因造成的?

这是函数:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string

  printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!

  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

我也试过了,这不会导致我遇到锁:

u8 GSM_Telit_ReadSms(u8 bSmsIndex)
{
  char bTmpSms[3] = {0};

  itoa(bSmsIndex, bTmpSms, 10);
  printf("index = 2\n");


  GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
  return 1;
}

没有启用任何优化,并且在尝试从我的 I²C RTC 中读取一个字节时代码会卡住,但只要我删除此 printf("index = %s\n", bTmpSms); 或使用此 printf("index = 2\n"); ,一切都会很愉快。有什么想法吗?

bSmsIndex 实际上永远不会超过 30,即使这样,在调用此函数之前也会发生锁定。

【问题讨论】:

  • 你是说即使这个函数没有执行一次也会发生锁定?
  • 是的,就是这样!
  • 哦 - 这是一个非常有趣的方面,直到现在我才知道。当您停留在读取 I2C RTC 时,堆栈跟踪是否显示任何有趣的东西?你在使用多任务处理吗?
  • @jramirez,如果你的答案是正确的,请接受它;)
  • @Colin 我知道,但它说“你可以在 2 天内接受你自己的答案”我想我将不得不等待抱歉

标签: c arm printf iar stm32


【解决方案1】:

char bTmpSms[3] 只有“99”的空间。如果您的 bSmsIndex 为 100 或更大,您将尝试写入不属于您的内存。


更新后编辑

我的本​​地机器上没有itoa 的引用,但我找到了这个(http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/)。根据该参考资料,目标数组必须足够长以获取任何可能的值。检查您的文档:您的具体 itoa 可能不同。

或者使用sprintf、snprintf,或者标准描述的一些功能。

【讨论】:

  • 正确,但这不是导致问题的写入(因为第二个代码有效)。是 printf 读取字符串会杀死事情。但是,写入也可能在某些时候引起问题,所以肯定也是一个问题
  • @Paul - 但谁知道这个错误的写法可能会破坏什么?
  • 就我而言,写入不属于您的内存可能会使您的程序将钱从您的银行账户转移到我的账户:-)
【解决方案2】:

一些想法:

如果itoa() 没有正确地以 NUL 终止字符串,那么对 printf 的调用可能会导致机器永远寻找 NUL。

pmg 有一个很好的观点。

另外,考虑itoa() 的第一个参数是什么类型。如果它是有符号的并且你传入一个无符号整数,那么你可能会在 bTmpSms 中得到一个意外的减号。尝试改用sprintf()。

【讨论】:

  • itoa 是空终止的,我检查了
【解决方案3】:

代码中的更改正在将其余代码移动到内存中。我的猜测是,此处未列出的代码的其他部分正在抨击某个随机位置;在第一种情况下,该位置包含一些关键的东西,在第二种情况下,它没有。

这些是最难追查的问题*。祝你好运。

*也许不是最糟糕的——如果它是每周只出现一次的多个线程之间的竞争条件,情况可能会更糟。仍然不是我最喜欢的那种错误。

【讨论】:

    【解决方案4】:

    似乎如果我不将变量 bTmpSms 初始化为某些东西,就会出现问题。

    我也意识到问题不是 printf。它是 itoa 函数。它让我检查,即使我不认为这是问题所在,当我评论 itoa 函数时,整个代码都可以工作。

    所以我最终这样做了:

    u8 GSM_Telit_ReadSms(u8 bSmsIndex)
    {
      char bTmpSms[4] = "aaa";    // I still need to find out why this is !!!
    
      itoa(bSmsIndex, bTmpSms, 10); // Converts the smsindex into a string
    
      printf("index = %s\n", bTmpSms); // This printf caused the code to get stuck in the RTC // byte read function!
    
      GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0);
      return 1;
    }
    

    这是我得到的 itoa 函数:

    char itoa(int value, char* result, int base)
    {
      // Check that the base if valid
      if (base < 2 || base > 36) {
          *result = '\0';
          return 0;
      }
    
      char* ptr = result, *ptr1 = result, tmp_char;
      int tmp_value;
    
      do
      {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsr
    

    qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; } 而(值);

      // Apply negative sign
      if (tmp_value < 0)
          *ptr++ = '-';
      *ptr-- = '\0';
      while(ptr1 < ptr)
      {
        tmp_char = *ptr;
        *ptr--= *ptr1;
        *ptr1++ = tmp_char;
      }
      return 1;
    }
    

    【讨论】:

    • 看我的回答。我不认为你解决了这个问题,我认为你掩盖了它。它稍后会回来咬你。
    • 我同意你的看法。这就是为什么我说我稍后会检查这个功能。但至少我知道大部分问题出在哪里。
    • 我希望我没有误解你 - 听起来问题甚至在调用 atoi 函数之前就已经显现,所以错误也不存在。你真的不知道问题出在哪里。
    • 只有在有 atoi 功能时才会出现问题。不,它没有到达那里。当函数被注释掉时,代码可以正确运行,以便给出问题所在的一些想法,我也将使用 sprintf( bTmpSms, "%d", bSmsIndex ) 似乎正在工作。再次是嵌入式编程,所以我需要一点时间来逐步完成代码找到问题所在,我会更新任何进展
    【解决方案5】:

    您尝试打印的bSmsIndex 的值是多少?

    如果它大于 99,那么您将超出 bTmpSms 数组。

    如果这没有帮助,那么使用 IAR 相当不错的调试器 - 我会在调用 printf() 的位置进入程序集窗口,然后单步执行,直到事情陷入困境。这可能会弄清楚问题所在。

    或者作为快速解决问题的方法,尝试将数组调整为较大的值(可能是 8 个),然后看看会发生什么。

    【讨论】:

    • 我确实尝试将数组变大,但出现了同样的问题
    • @jramirez:我认为您可能需要卷起袖子,开始踏入运行时的深渊……
    【解决方案6】:

    bSmsIndex 的值是多少?

    如果超过 99,则转换为字符串时为三位数。当零终止时,它将是四个字符,但是您只为 bTmpSms 分配了三个字符,因此空值可能会被覆盖,并且 printf 将尝试打印 bTmpSms 之后的任何内容,直到下一个空值。那真的可以访问任何东西。

    【讨论】:

      【解决方案7】:

      尝试用 index = 2 vs. index = %s 分解这个区域。

      【讨论】:

        猜你喜欢
        • 2021-06-21
        • 2018-09-24
        • 1970-01-01
        • 2017-08-29
        • 2015-04-04
        • 2017-07-01
        • 2023-03-24
        • 2021-12-16
        • 1970-01-01
        相关资源
        最近更新 更多