STM32 printf и RTC - PullRequest
       70

STM32 printf и RTC

3 голосов
/ 12 октября 2010

* ОБНОВЛЕНИЕ *

Вот что я нашел. Всякий раз, когда у меня была эта функция, код не блокировался. Это на самом деле сделало бы функцию чтения RTC I²C очень медленной для выполнения, но код все равно работал бы правильно, но мне приходилось ждать очень долго, чтобы пройти каждый раз, когда я читал RTC.

Таким образом, существует аварийное прерывание для RTC, и это вызвало другие взаимодействия I²C внутри ISR, поэтому похоже, что он пытался выполнить два обмена данными I²C одновременно, что замедляет процесс. Я удалил функции в ISR, и теперь он работает. Я буду продолжать расследование.

<Ч />

У меня возникла эта проблема при программировании микроконтроллера STM32F103 с использованием IAR 5.40. У меня есть эта функция, которая, если я пытаюсь напечатать локальную переменную, приводит к зависанию кода в другом месте, прежде чем он даже доберется до рассматриваемой функции.

Что может быть причиной этого?

Это функция:

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;
}

Оптимизация вообще не включена, и код застревает при попытке прочитать байт из моего ITC-RTC, но как только я удаляю этот printf("index = %s\n", bTmpSms); или использую этот вместо printf("index = 2\n");, тогда все устраивает. Есть идеи?

bSmsIndex никогда не будет больше 30 на самом деле, и даже в этом случае блокировка происходит до того, как эта функция будет вызвана.

Ответы [ 7 ]

2 голосов
/ 12 октября 2010

char bTmpSms[3] имеет место только для "99". Если ваш bSmsIndex равен 100 или больше, вы будете пытаться записывать в память, которая вам не принадлежит.


Редактировать после обновления

У меня нет ссылки на itoa на моей локальной машине, но я нашел эту (http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/). Согласно этой ссылке, массив назначения ДОЛЖЕН БЫТЬ ДОЛГО ДОСТУПНЫ ДЛЯ ЛЮБОГО ВОЗМОЖНОГО ЗНАЧЕНИЯ Проверьте документацию: ваш конкретный itoa может отличаться.

Или используйте sprintf, snprintf или какую-либо функцию, описанную в Стандарте.

1 голос
/ 13 октября 2010

Похоже, что если я не инициализирую переменную bTmpSms чем-то, возникает проблема.

Я также понял, что проблема не в printf. Это функция Итоа. Это заставило меня проверить, что, хотя я и не думал, что это было проблемой, когда я комментировал функцию 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 - значение * base)]; } while (значение);

  // Apply negative sign
  if (tmp_value < 0)
      *ptr++ = '-';
  *ptr-- = '\0';
  while(ptr1 < ptr)
  {
    tmp_char = *ptr;
    *ptr--= *ptr1;
    *ptr1++ = tmp_char;
  }
  return 1;
}
1 голос
/ 13 октября 2010

Изменение в коде перемещает остальную часть вашего кода в памяти.Я предполагаю, что какая-то другая часть кода, не перечисленная здесь, избивает какое-то случайное место;в первом случае это местоположение содержит что-то критическое, во втором - нет.

Это наихудшие проблемы для отслеживания *.Удачи.

* Возможно, не самое худшее - могло бы быть хуже, если бы это было состояние гонки между несколькими потоками, которое проявлялось только раз в неделю.Все еще не мой любимый вид ошибки.

1 голос
/ 12 октября 2010

Некоторые идеи:

Если itoa() неправильно завершает строку NUL, то вызов printf может привести к тому, что устройство будет всегда искать NUL.

ПМГ имеет очень хорошую точку.

Также рассмотрим тип первого аргумента itoa(). Если он подписан и вы передаете целое число без знака, то вы можете получить неожиданный знак минуса в bTmpSms. Попробуйте использовать sprintf() вместо.

0 голосов
/ 12 октября 2010

Попробуйте разобрать эту область с индексом = 2 против индекса = %s.

0 голосов
/ 12 октября 2010

Какое значение bSmsIndex вы пытаетесь напечатать?

Если значение больше 99, то вы заполняете массив bTmpSms.

Если это не поможет, используйте довольно хороший отладчик IAR - я бы заглянул в окно сборкив точке, где вызывается printf() и один шаг, пока все не уйдет в сорняки.Это, вероятно, прояснит, в чем проблема.

Или как быстрое устранение неполадок, попробуйте изменить размер массива до чего-то большого (возможно, 8) и посмотрите, что произойдет.

0 голосов
/ 12 октября 2010

Какое значение bSmsIndex?

Если больше 99, при преобразовании в строку оно будет трехзначным.Когда завершится ноль, это будет четыре символа, но вы выделили только три для bTmpSms, так что нуль может быть перезаписан, и printf попытается напечатать все, что следует после bTmpSms, до следующего ноля.Это может получить доступ ко всему, на самом деле.

...