Я использую отладчик ST Link на микроконтроллере STM32F407. У меня есть проблемы, связанные с неправильной загрузкой данных между различными кольцевыми буферами, используемыми для извлечения байтов из USART. Я хотел посмотреть, как поток, извлекающий кадры из массива serial [4000], ведет себя с добавленной задержкой.
Нижеприведенный код отлично работает с отладчиком, и я могу входить в каждую строку и проверять значения переменных.
//This callback is automatically called by the HAL when the DMA transfer is completed
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// read 50 bytes of raw data to the raw_serial buffer
HAL_UART_Receive_DMA (huart, raw_serial, 50);
//osDelay(10);
//HAL_Delay(10);
// add raw_serial to the serial[4000]
AppendSerial(raw_serial,size);
}
Используя любую из этих задержек:
osDelay(10);HAL_Delay(10);Вызывает зависание выполнения программы в одном из циклов обратного отсчета и не позволяет мне когда-либо достичь точки останова, расположенной после состояния ожидания.
Читая этот Почта, мне кажется, что osDelay более уместен при использовании FreeRTOS.
Единственные причины, по которым я могу думать, это отсутствие совместимости или драйверов ST Link или невозможность включить задержки из функций обратного вызова, запускаемых прерыванием.
Спасибо за вашу помощь.





Вы не можете вызвать функцию задержки из обработчика прерывания. Помните, что цель обработчиков прерываний состоит в том, чтобы выполняться как можно быстрее, чтобы программа могла вернуться к нормальному выполнению, задержка несовместима с этой концепцией.
Это не имеет ничего общего с ST-Link.
По умолчанию функции задержки работают, отслеживая переменную, которая увеличивается при прерывании таймера. Если это прерывание таймера заблокировано, переменная не увеличивается, и функция задержки никогда не завершится. Есть несколько способов обойти это.
Разрешить прерыванию по таймеру вытеснять обработчик последовательных прерываний
Убедитесь, что прерывание по таймеру имеет более высокий приоритет, чем последовательное прерывание. По умолчанию HAL устанавливает прерывание таймера с самым низким приоритетом (довольно глупая идея, IMO) в stm32f4xx_hal_conf.h
#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */
измените это на более низкое значение (более высокий приоритет) и установите приоритет прерывания UART на более высокое значение (более низкий приоритет). Теперь HAL_Delay() будет работать даже в обработчике прерываний UART.
Заставьте HAL_Delay() работать без перерывов
HAL_Delay() работает путем многократного вызова HAL_GetTick(), пока не истечет время задержки. HAL_GetTick() должен возвращать время, прошедшее с момента запуска в миллисекундах, в виде 32-битного значения без знака. Вы можете предоставить свою собственную реализацию HAL_GetTick(), которая использует 32-битный аппаратный таймер для определения текущего времени.
Есть два 32-битных таймера, TIM2 и TIM5, выберите один из них. Установите значение перезагрузки равным тактовой частоте APB1, деленной на 1000 минус 1 (83999 с настройками часов по умолчанию), начните отсчет вверх. Теперь HAL_GetTick() может просто вернуть регистр счетчика таймера.
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
Напишите свою функцию задержки
Например, вы можете использовать счетчик циклов для коротких задержек или пустой цикл for, чтобы иметь приблизительные задержки, запустить одноразовый таймер и дождаться завершения и т. д.