Переменная, инициализированная в цикле for, содержит значение, не увеличивается

Я работаю над функцией для микроконтроллера STM32, который отправляет строку заданной длины через порт uart. Чтобы обрабатывать связь uart, я создал класс Serial, у которого есть буфер передачи и приема, которые извлекаются и передаются в обработчике прерывания. Функция, над которой я сейчас работаю, на самом деле является перегрузкой функции, которую я написал ранее, которая работает. Ниже представлена ​​рабочая функция:

void Serial::sendString(char* str) {
// Writes a string to txBuffer. If Transmit interrupts are enabled, and
// the Data register is empty, the txBuffer will be popped into the DR to
// prime the interrupts.

__HAL_UART_DISABLE_IT(uart, UART_IT_TXE); // Keeps our spaghetti straightened out...

while (*str != '\0') { // While char is not a null terminator...
    txBuffer->push(*str); // Push first char into queue as we know it is valid
    str++; // Pointer goes to next char in string
}

 uint32_t isrflags   = READ_REG(uart->Instance->SR); // Reads the flags and control register
 //uint32_t cr1its     = READ_REG(uart->Instance->CR1); // Into variables

 // If the DR is empty and Transmission interrupts are disabled...
 if ((isrflags & USART_SR_TXE) != RESET) {
    uart->Instance->DR = txBuffer->pop(); // Reenable interrupts and prime the DR
    }

 __HAL_UART_ENABLE_IT(uart, UART_IT_TXE); // Alright, time to cook the pasta

}

Перегрузка - это функция, с которой у меня возникли проблемы. По какой-то причине отладчик показывает, что переменная i инициализируется значением 14 и не увеличивается при переходе с помощью отладчика. Фактически, отладчик вообще не позволяет мне войти в цикл for. Вот такая перегрузка:

void Serial::sendString(char* str, unsigned int len) {
// Writes a string to txBuffer. If Transmit interrupts are enabled, and
// the Data register is empty, the txBuffer will be popped into the DR to
// prime the interrupts.
// Rather than being terminated by a null character, this method instead
// sends each char in an array of a specified length. Note that this overload
// MUST be used in any situation that a null terminator might appear in a char
// array!

__HAL_UART_DISABLE_IT(uart, UART_IT_TXE); // Keeps our spaghetti straightened out...

for (unsigned int i = 0; i < len; i++) { // While char is not a null terminator...
    txBuffer->push(str[i]); // Push first char into queue as we know it is valid
    //str++; // Pointer goes to next char in string
}

 uint32_t isrflags   = READ_REG(uart->Instance->SR); // Reads the flags and control register
// uint32_t cr1its     = READ_REG(uart->Instance->CR1); // Into variables

 // If the DR is empty...
 if ((isrflags & USART_SR_TXE) != RESET) {
    uart->Instance->DR = txBuffer->pop();
    }
 __HAL_UART_ENABLE_IT(uart, UART_IT_TXE); // Alright, time to cook the pasta

}

Эти функции вызываются внутри терминального цикла while в main. При отладке проблемы возникают немедленно; Я вообще не могу выдержать перегрузку. Кажется, мой код просто зашел в тупик в этом месте.

Раньше мне удавалось успешно запускать перегрузку. Эта ошибка появилась только тогда, когда я пытался исправить другую ошибку в функции, когда первый символ в строке передавался только половину времени. Я установил точку останова и начал отладку, а теперь она вообще не работает ....


person Jonathan Just    schedule 01.02.2021    source источник
comment
Обновление: я перезапустил свою IDE, заменил свою плату на другую, прошил код, и он волшебным образом начал работать. Я немного новичок в разработке прошивок, может ли кто-нибудь объяснить, что могло вызвать эти странные ошибки? Они кажутся довольно маленькими и специфичными для аппаратной части ...   -  person Jonathan Just    schedule 01.02.2021
comment
кстати, ваш код имеет очень мало смысла. Обработка прерываний должна выглядеть совершенно иначе. Он работает случайно и перестанет работать, когда вы напишете больше кода.   -  person 0___________    schedule 01.02.2021
comment
Не могли бы вы уточнить? Плата, с которой я работаю, имеет прерывание, которое срабатывает, когда регистр данных очищается после передачи. В моем ISR я вставляю то, что находится в txBuffer, в DR для передаваемого байта.   -  person Jonathan Just    schedule 01.02.2021
comment
Вы просто делаете это неправильно. Посмотрите любой достойный STM32 код IT UART и найдите различия. Это слишком много, чтобы объяснять комментарий.   -  person 0___________    schedule 01.02.2021
comment
Привет, я заглянул в код передачи прерывания STM32. Неправильно ли помещать данные в DR в методе отправки? Спасибо за ваш отзыв   -  person Jonathan Just    schedule 01.02.2021
comment
Думаю, вы не понимаете, для чего нужны прерывания и как их использовать.   -  person 0___________    schedule 01.02.2021
comment
Отключите любую оптимизацию компилятора и посмотрите, ведет ли отладчик ожидаемое вами поведение. Оптимизатор может оптимизировать переменные и циклы, и пошаговое выполнение оптимизированного кода может вести себя не так, как вы ожидаете.   -  person kkrambo    schedule 01.02.2021
comment
В значительной степени существует только два действительных способа получения большого количества данных от UART в сложной программе. Либо какой-либо способ FIFO кольцевого буфера, в который записывается прерывание rx. Или предпочтительно, используя DMA, если он доступен. Для более простых приложений может работать и третий вариант быстрого опроса rx-буфера.   -  person Lundin    schedule 02.02.2021
comment
В противном случае классическая проблема заключается в том, что у вас есть периферийное устройство UART с регистрами состояния, которые очищаются путем их чтения. Отладчик, отображающий эти регистры на карте памяти, может случайно уничтожить эти регистры. Обычно вы замечаете это, когда код работает нормально, но не в пошаговом режиме. Хотя в случае с Eclipse отладчик настолько ужасен, что вы с трудом можете заставить его создать карту памяти ...   -  person Lundin    schedule 02.02.2021


Ответы (1)


Похоже, компилятор оптимизировал ваши переменные управления циклом.

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

На самом деле вы не описали, в чем проблема, которую вы пытаетесь отладить. Вместо того, чтобы ожидать, что процесс отладки будет идеальным, просто попытайтесь решить проблему, которая у вас возникла, несмотря на то, что мне всегда было 14 лет!

Глядя только на опубликованный вами код, я не вижу большой проблемы. Конечно, в коде, который вы не показываете, может быть ошибка.

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

Запись первого байта в UART в этой функции позволяет сэкономить на стоимости одного прерывания, но если вы пишете строку из 20 байтов, вас действительно волнует, требуется ли для этого 20 или 19 прерываний? Хороший принцип дизайна заключается в том, что вам следует усложнять код только в том случае, если он дает вам то, без чего вы не хотите оставаться.

person Tom V    schedule 02.02.2021
comment
Отладчики не оптимизируют код. Что касается компилятора, он не будет оптимизировать код, содержащий операции чтения / записи в регистры периферийных устройств. Если это происходит, то это может быть только потому, что весь код определения регистра не работает, что кажется надуманным. - person Lundin; 02.02.2021
comment
Просто опечатка ... исправлено. - person Tom V; 02.02.2021
comment
Спасибо за ваш отзыв! Проблема заключалась в том, что я пытался решить БЫЛА проблема с зависанием переменной, я работал над внедрением протокола Dynamixel 2.0 в более крупный проект, когда мой код просто волшебным образом перестал работать. Я не уверен, была ли ошибка в оптимизации, потому что у меня были проблемы в моих сборках отладки и выпуска ... Проблема исчезла, когда я заменил другую плату и повторно подключил свой ST-Link ... Пока что я действительно не смог воспроизвести ошибку, но я обновлю эту ветку, если я когда-нибудь снова столкнусь с проблемой ... - person Jonathan Just; 03.02.2021
comment
Вы можете принять ответ? Благодарю. - person Tom V; 03.02.2021