verlaty

Stm32: Cubemx+Uart_Dma

68 сообщений в этой теме

verlaty    0

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

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

Я там еще пробелы добавляю и конец строки (перевод каретки + ноль символ) чтобы удобнее читать было

как только прием встал, анализируем последние байты и смотрим что там получилось. Делаем выводы

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

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Кажется выловил ошибку.

huart1.ErrorCode выдает 8.

а это HAL_UART_ERROR_ORE ((uint32_t)0x00000008) /*!< Overrun error

ORE — ошибка: переполнение входного буфера — приняты новые данные, а старые ещё не прочитаны

во всяком случае есть куда капать.

Буду разбираться. Если есть дельные советы - внимательно слушаю

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

для начала попробовать

__HAL_UART_FLUSH_DRREGISTER(&huart1);

первой строчкой в колбэке

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

verlaty    0

Пробую сбрасывать флаг

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
E_CODE = HAL_UART_GetError (huart);
switch (E_CODE)
{
case HAL_UART_ERROR_ORE:
 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
 CLEARFL = HAL_UART_GetError (huart);
break;
}

сделал переменную CLEARFL для контроля

Ну в общем не сбрасывает. Кто сталкивался с этой бедой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

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

см. предыдущий пост

ну и сам подход неверен. Сбросить флаг в железе может быть совсем не одно и то же для HAL. Лучше использовать макрос сброса (для F1 и F0)

для трешки еще можно попробовать вот эти вот макросы

UART Advanced Feature Overrun Disable

UART_ADVFEATURE_OVERRUN_ENABLE

UART_ADVFEATURE_OVERRUN_DISABLE

IS_UART_OVERRUN

единственное я на них доки не нашел, лучше посмотреть что там в них за код и покумекать как их поставить раком

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Точно. Надо сначала очистить буфер.

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
E_CODE = HAL_UART_GetError (huart);
switch (E_CODE)
{
 case HAL_UART_ERROR_ORE:
  __HAL_UART_FLUSH_DRREGISTER(huart);
  __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
  CLEARFL = HAL_UART_GetError (huart);
 break;
}
}

Не прокатило

Изменено пользователем verlaty

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

отписал в добавку постом выше. Возможно не тот метод

возможно еще надо сделать status_reset после сброса флага

есть макрос очистки флага без функции

UART_CLEAR_OREF

OverRun Error Clear Flag

поставь в код и почитай чего там написано. (у меня либы F3 нет)

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

В Кубе можно отключить overrun в конфигурации USART. Раз эта опция есть, значит ее можно тыкать.Вопрос на что это повлияет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

вот это уже хз. не проверял

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

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

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

I ran into a similar problem as yours a few months ago on a Cortex M4 (SAM4S). I have a function that gets called at 100 Hz based on a Timer Interrupt.

In the meantime I had a UART configured to interrupt on char reception. The expected data over UART was 64 byte long packets and interrupting on every char caused latency such that my 100 Hz update function was running at about 20 Hz. 100 Hz is relatively slow on this particular 120 MHz processor but interrupting on every char was causing massive delays.

I decided to configure the UART to use PDC (Peripheral DMA controller) and my problems disappeared instantly.

DMA allows the UART to store data in memory WITHOUT interrupting the processor until the buffer is full saving lots of overhead.

In my case, I told PDC to store UART data into an buffer (byte array) and specified the length. When UART via PDC filled the buffer the PDC issued an interrupt.

In PDC ISR:

  1. Give PDC new empty buffer
  2. Restart UART PDC (so can collect data while we do other stuff in isr)
  3. memcpy full buffer into RINGBUFFER
  4. Exit ISR

As swineone recommended above, implement DMA and you'll love life.

короче говоря, убирай ожидание первого байта по прерыванию и читай все по ДМА. Попробовать так

там еще написано следующее

типок выделил для ДМА кольцевой буфер, и как только тот заполнялся, он входил в прерывание ДМА и выделял ему новый буфер, а старый в это время обрабатывал. Как то так

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

тема изначально назвалась Cubemx + uart_dma. Заметил такую вещь. Один уарт у меня принимает пачки по 8 байт второй по 3. Тот который по 8 практически не зависает, а вот по 3 постоянно. Хотя все реализовано аналогично, на одной плате, на оном камне, но факт на лице.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

почитал буржуев. В общем оверран возникает тогда, когда не успеваешь прочитать предыдущий байт, а следующий уже начал приниматься (откапитанил). Флаг оверрана может не сбрасываться программно, до тех пор пока байт не будет физически прочитан из буфера (то есть он не затирается, а ждет чтения). Очистка регистра данных может и поможет, а может и нет. Судя по всему не помогает. Или следующий оверран просто перетирает флаг быстрее чем оклимается контроллер.

Выводы.

Надо делать непрерывный прием в некий буфер в памяти. У меня таким буфером была очередь, поэтому видимо все и успевало, хотя принимал я по одному символу и камень был F103. Очевидно надо думать как ускорить чтение или организовывать буфер. Костыли типа сброса флага не помогут.

Возможно на первом канале приоритет прерываний или канала DMA выше, поэтому он и не глючит так.

Печалька

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

вот так вот происходила обработка из очереди в операциоке. В принципе обрабатывалось по одному байту. Можно попробовать сделать прием в буфер длинной 1 байт и обрабатывать на лету прямо в колбэке приема. До 0,9 мегабита работает железобетонно на камне F051 и F103 (частотки 48 и 72 МГц соответственно)

void StartUserTask01(void const * argument)
{
char lReceivedValue;
portBASE_TYPE xStatus;
const portTickType xTicksToWait = 1000 / portTICK_RATE_MS;
short int rxindex = 0;
uint8_t ErrorFlag = UART_PACKET_OK;
char rxString[MAXSTRING];

for( ;; )
{
UBaseType_t i = 0;
i = uxQueueMessagesWaiting( myQueue01Handle );
while (i != 0)
{
xStatus = xQueueReceive( myQueue01Handle, &lReceivedValue, xTicksToWait );
 if( xStatus == pdPASS )
 {
 if (lReceivedValue == 8 || lReceivedValue == 127) // If Backspace or del
{
rxindex--;
if (rxindex < 0) rxindex = 0;
}
else if (lReceivedValue == '\n') // If Enter
{
if (ErrorFlag == UART_PACKET_OK)
{
 rxString[rxindex] = '\n';
 rxindex++;
 rxString[rxindex] = 0;

 rxindex = 0;

 command_processor(rxString); // command handler
}
else
{
 //TODO - UART Error handler
 ErrorFlag = UART_PACKET_OK; // reset error state
}
}
else
{
if (lReceivedValue != '\r' && ErrorFlag == UART_PACKET_OK) // Ignore return
{
 rxString[rxindex] = lReceivedValue; // Add that character to the string
 rxindex++;
 if (rxindex >= MAXSTRING) // User typing too much, we can't have commands that big
 {
 ErrorFlag = UART_PACKET_TOO_LONG;
 rxindex = 0;
 rxString[rxindex] = '\000';
 }
}
}
 }
 else
 {
 taskYIELD();
 }
i--;
}
}
}

счас нарою проект с голым уартом на эту тему

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

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static short int rxindex = 0;
static uint8_t ErrorFlag = UART_PACKET_OK;
//__HAL_UART_FLUSH_DRREGISTER(&huart1); // Clear the buffer to prevent overrun
if (rxBuffer == 8 || rxBuffer == 127) // If Backspace or del
{
rxindex--;
if (rxindex < 0) rxindex = 0;
}
else if (rxBuffer == '\n') // If Enter
{
if (ErrorFlag == UART_PACKET_OK)
{
rxString[rxindex] = rxBuffer; // Add that character to the string
rxindex++;
rxString[rxindex] = 0;
rxindex = 0;
if (huart->State != HAL_UART_STATE_BUSY_TX_RX) UART_Send (rxString);
}
else
{
if (huart->State != HAL_UART_STATE_BUSY_TX_RX) UART_Send ("ERROR > UART packet too long\n");
ErrorFlag = UART_PACKET_OK; // reset eeror state
}
}
else
{
if (rxBuffer != '\r' && ErrorFlag == UART_PACKET_OK) // Ignore return
{
rxString[rxindex] = rxBuffer; // Add that character to the string
rxindex++;
if (rxindex >= MAXSTRING) // User typing too much, we can't have commands that big
{
ErrorFlag = UART_PACKET_TOO_LONG;
rxindex = 0;
rxString[rxindex] = '\000';
}
}
}
}

могу прям проектами в почту отправить целиком. (все под Keil правда)

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
mail_robot    1 414

да, именно так. Буфер на один символ. Принимает все подряд до тех пор пока не примет \n. Дальше передает принятое в обработчик строки. Работало 100%

могу отправить весь проект. Но там ничего особенного. В мэйне стартует прием по дма сразу после инитки и в глобальных переменках определен односимвольный буфер. Все стандартно

ну и еще определен глобальный массив под строку для складирования в колбэке. ДМА читает в односимвольный буфер, а колбэк из него пихает в массив который управляется rxindex. ДМА работает в цикле и никогда не останавливается

суть в чем - даже если прерывания не будут поспевать за приемом, то оверрана не будет. Просто потеряется символ и все на этапе обработки. Но до 0,9М такого не происходило. Реальные потери начинаются гдето в районе 1,3...1,5Мб/с. На 3,5 Мб/с теряется примерно каждый 3-й символ

Изменено пользователем mail_robot

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
verlaty    0

Запустил UART в режим DMA circular. Слегка подправил свой код для работы в этом режиме, без постоянных запусков HAL_UART_Receive_DMA . Все проблемы снялись, все работает. Отдельное спасибо mail_robot за активную помощь и участие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Сообщения

    • Автор темы обозначил себя как житель Минска, а у них там Польша рядом и прочая Европа. Должно ловиться хоть что-то.
    • Привет всем! Решил собрать первый усь класса Д. Помогите проверить расчет дросселя. Питание уся будет +-35В, нагрузка 8 Ом. Схема, сердечник (броневой д-30 мм высота 19), расчет прилагаю.
    • Это да,кто спорит. Аж целое ламантерское радиво Я как вспомню эти пионеры 5.1 и 7.1 в дрожь кидает. Ух в ремонте..ну падлы тухлые Я от чет задумался-а у нас есть чего на составниках то приличное? Завтра платку заберу от Kenwood-а с составными..
    • Хорошо на будущее учту   Именно так они были соединены в 25АС309 в Советском Союзе  Насколько я понял, такая схема практиковалась для получения неполярных кондеров
    • Прямого усиления сейчас не нужно делать на куче транзисторов. Копеечная TA7642 в помощь. Там в конце статьи видео, ловится вечером в центре России (Саратовская область) больше десятка станций.
    • Смысла не вижу в брелке с GPS - точность плюс-минус несколько десятков метров, да и не во всяком помещении он будет работать. Разве только как трекер - жучок его использовать. ps.А по теме - проще приучить себя к порядку. Сам за всю жизнь ни разу ключи не терял. Они либо висят на специальном гвоздике в прихожей, либо в надежном выделенном кармашке - и нигде больше находиться не имеют права. Это действительно работает. pps.Касается не только ключей, но и других бытовых ситуаций, например "куда делся метчик на М4, черт бы его побрал!". Ну вы поняли.
    • Это в тебе щаз говорит старый ламантёр, объевшийся всякими всякостями в СЦ. А вообще-то такой простейший лин, еж ли его сделать с умом, может очень даже не плохо звучать, имея в спектре короткий хвост чётных гармошек, начиная со 2-й на уровне не более 0.1% и с нечётными на уровне сотых, что вполне достаточно, для того, чтобы кому-то, кто не избалован хаендами, нравиться. И, кстати, по поводу "100 ватт на коленке". Был когда-то в ходу такой KIT - velleman VM-100, который до сих пор продаётся diy-ерами в штатах и периодически предлагается к продаже, всплывая в СНГ, потеряв только при этом в нике первую букву и обретя "2" вместо "1"  - звучит вполне-таки неплохо, хотя по сути он-то как раз и есть "100 ватт на коленке" - usermanual_vm100_rev1.pdf ЗЫ. У Макса Васильева была схемашка "100 ватт на коленке" с УН-ом "шушурина" - среди бюджетников ещё надо поискать балалайку, что бы так вкусно играла.