Чрезвычайно специфическая проблема компилятора - PullRequest
2 голосов
/ 14 декабря 2011

Я написал код для PIC16F1947 на C. Я использую следующее:

  • MPLAB IDE 8.73
  • HI-TECH C Компилятор 9.81

Часть кода связана с данными, поступающими с ПК. Конкретный пакет, который я посылаю с ПК, составляет 325 байт. Этот пакет выглядит следующим образом:

data:  0, 64, 1, 0, 255, 255, 255, ... (all 255) ..., 255,   1
index: 0   1  2  3    4    5    6                     323  324

Содержимое пакета отображается в виде 8-разрядного десятичного значения (8-разрядное целое число без знака). Микро хранит его в массиве unsigned char:

unsigned char _command_mgr_buff[330];

unsigned char - 8-битное целое число без знака для PIC16F.

Последний байт пакета, то есть индекс 324, является контрольной суммой пакета. Это сумма индексов с 1 по 323, включая 1 и 323. Код ПК (в C #), который вычисляет эту контрольную сумму, выглядит следующим образом:

allCertPages[324] = 0;
for (int i = 1; i <= 323; i++)
{
    allCertPages[324] += allCertPages[i];
}

allCertPages является byte[].

Микро должен проверить, что контрольная сумма действительно является значением, переданным с ПК. Вот код подтверждения, который я написал для PIC16F, включая некоторую отладочную информацию:

param0 = _command_mgr_buff[324]; // param0 is unsigned int, 16 bit
param1 = _command_mgr_buff[324]; // param1 is unsigned int, 16 bit

// Checksum verification
for (var = 1; var <= 323; var++) // var is unsigned int, 16 bit
{
    _command_mgr_buff[324] -= _command_mgr_buff[var];
    param1 -= _command_mgr_buff[var];
}

if (!_command_mgr_buff[324])
{
    send_status(CS_BAD_PARAM);
}

Идея состоит в том, чтобы вычесть все значения в диапазоне [1, 323] из контрольной суммы. Если конечное значение равно 0, то контрольная сумма верна. В противном случае, если _command_mgr_buff[324] будет найдено ненулевым после вычитания, то контрольная сумма будет неправильной.

После выполнения кода в режиме отладки (а также в режиме выпуска) я получаю ненулевое значение в _command_mgr_buff[324] (поэтому send_status(CS_BAD_PARAM); выполняется, и ПК считает, что что-то не так), но ноль в младший байт param1!

Как это возможно?!

Если вам интересно, вот сборка, сгенерированная для ненулевой проверки:

  8780                           ;mgr_command.c: 1230: if (!_command_mgr_buff[324])
  8781  0E89  30EA                  movlw   low(8870+0144h)
  8782  0E8A  00D3                  movwf   (??_command_mgr_run+0)^080h+0
  8783  0E8B  3023                  movlw   high(8870+0144h)
  8784  0E8C  00D4                  movwf   (??_command_mgr_run+0)^080h+0+1
  8785  0E8D  0853                  movf    0+(??_command_mgr_run+0)^080h+0,w
  8786  0E8E  0086                  movwf   fsr1l
  8787  0E8F  0854                  movf    1+(??_command_mgr_run+0)^080h+0,w
  8788  0E90  0087                  movwf   fsr1h
  8789                           
  8790  0E91  0881                  movf    indf1,f
  8791  0E92  1D03                  skipz
  8792  0E93  2E95                  goto    u10101
  8793  0E94  2E96                  goto    u10100
  8794  0E95                     u10101:
  8795  0E95  2E9B                  goto    l55070
  8796  0E96                     u10100:
  8797                              line    1232
  8798                              
  8799  0E96                     l55068:    
  8800                           ;mgr_command.c: 1231: {
  8801                           ;mgr_command.c: 1232: send_status(0x11);
  8802  0E96  3011                  movlw   (011h)
  8803  0E97  31B6  2693  3188      fcall   _send_status
  8804                              line    1233
  8805                           ;mgr_command.c: 1233: }
  8806  0E9A  2FE3                  goto    l45048
  8807                              line    1234

Вот скриншот, сделанный во время отладки. Пожалуйста, проверьте окно Watch справа и подсказку для 324-го элемента.

  • param0 должно быть 1
  • param1 & 0xFF должно быть 0
  • _command_mgr_buff[324] должно быть 0 (подсказка показывает 0x0F ?? !!)

PIC16F Debug

1 Ответ

8 голосов
/ 14 декабря 2011

Если ваш код, как вы говорите, главной проблемой здесь является сам ваш тест:

if (!_command_mgr_buff[324])
{
    send_status(CS_BAD_PARAM);
}

Вы отправляете сигнал, если результат соответствует желаемому (а именно, нулю) ...

Это одна из причин, почему мне не нравится булево тестирование не булевых значений.Булевы переменные часто имеют имена, которые вынуждают вас правильно прочитать условие, которое они записывают, например if (isLoaded) или if (!anyErrors) ... и это не распространяется на числа.Так что проще убедиться, что у вас есть семантика, которую вы хотите записать:

if (_command_mgr_buff[324] != 0) 
{
    send_status(CS_BAD_PARAM);
}

Что касается того, почему ваш отладчик дает вам 0x0F ... там вам ничем не поможет ..Я просто хочу сказать, что вы в нулевой ветви.Вы можете попробовать чистую сборку и посмотреть, говорит ли она по-прежнему.(Символы отладки программы могут быть устаревшими или что-то в этом роде?)

...