Перейти к содержанию
    

От коллизий в RS485 вы так не защититесь. Это поможет сделать только протокол обмена.

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

В протоколе тоже есть свои байты для проверке. Но я писал про ситуацию, определение 1-го байта, а потом уже не важно, поэтому будет он первый или второй мне не важно, т.к. таймаут будет выбран с запасом. Та к ещё не попробывал сравнение со счётчиком, времени не было

 

В частности вопрос: если работать на приём так:

Получаю IDLE-прерывание, в его обработчике запрещаю канал DMA, копирую данные из буфера DMA в программное FIFO, настраиваю канал DMA заново на приём в буфер DMA, разрешаю DMA, выхожу из ISR. Могут-ли в таком алгоритме быть потери байт или другие проблемы?

 

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

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


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

копирую данные из буфера DMA в программное FIFO, настраиваю канал DMA заново на приём в буфер DMA

Почему нельзя настроить ДМА на запись данных в программное FIFO? Зачем это копирование?

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


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

Почему нельзя настроить ДМА на запись данных в программное FIFO? Зачем это копирование?
Это для общего случая. В частном случае, если структура программного FIFO позволяет, конечно возможно.

 

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


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

Если вероятность потери !=0, то на помойку такое ПО. Которое может работать с некоторой вероятностью в зависимости от фазы луны.

А если между проверкой и сбросом DMA как раз и придёт байт? И что значит "ресет DMA"? Это именно сброс канала или запрет его работы? Есть-ли у DMA каналов в STM32 FIFO? Знаю что у многих других контроллеров - есть, что будет приводить к потерям байт (при сбросе DMA) или появлению лишних байт (при его запрете) - сам лично сталкивался с такой проблемой.

Сброс DMA занимает доли микросекунды. Стек на ДМА в F2/F4 отключаемый (в данном случае он не используется).

Для того, чтоб вероятность потери свести к 0 на время сброса DMA нужно переключать прием на прерывание по RX. Однако, для GSM модема с его логикой это не обязательно, пропусков не наблюдается, для GPS тем более проблемы нет. Мы же работаем с реальными устройствами и знаем как они фунциклируют. Говоря о вероятности ошибки, я допускаю, что существует такой девайс которые не сможет работать через этот драйвер.

Эта идея не просто замена стека, а возможность дать процессору время для сна. В основном это актуально про использовании ОС. просто аппаратный стек эту задачу вообще никак не решает.

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

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


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

А может быть, потери в таком случае и не случится? Просто в момент включении DMA будет взведён флажок RXNE, и принятый байт из UARTx->DR благополучно отправится в буфер DMA.

Наверное это можно достаточно просто проверить - принять байт, не вычитывая его, и затем включить DMA.

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


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

Сброс DMA занимает доли микросекунды.
Т.е. - если скажем сброс занимает 0.1мкс и через UART за сутки у вас проходит скажем 10МБ данных (вполне реальная ситуация - через интерфейс обычного счётчика электроэнергии может проходить и больше), то вероятность потери раз в сутки близка к 100%?

А если скажем у вас работает система сбора данных из ста таких устройств? Будет сто сбоев в сутки? :twak:

Но даже если траффик меньше, значит сбои будут происходить реже, что ещё хуже, так как найти причину таких сбоев будет крайне сложно. Лучше было сразу уволить программиста с такими кривыми руками ;)

 

Стек на ДМА в F2/F4 отключаемый (в данном случае он не используется).
Стек в DMA??? :wacko: Это новость! Всегда считал что в канале DMA может быть FIFO, но никак не LIFO...

 

Для того, чтоб вероятность потери свести к 0 на время сброса DMA нужно переключать прием на прерывание по RX. Однако, для GSM модема с его логикой это не обязательно, пропусков не наблюдается, для GPS тем более проблемы нет. Мы же работаем с реальными устройствами и знаем как они фунциклируют. Говоря о вероятности ошибки, я допускаю, что существует такой девайс которые не сможет работать через этот драйвер.
Выйдет новая прошивка для вашего GSM-модема, или захотите заложить другой модем, потому что старого уже не купить, и в новой прошивке модем станет немножко по другому слать данные в UART (скажем - с небольшими паузами) и где будет ваше ПО? :)

 

Эта идея не просто замена стека, а возможность дать процессору время для сна. В основном это актуально про использовании ОС. просто аппаратный стек эту задачу вообще никак не решает.
По-моему Вы путаете стек с FIFO - это вообще-то совершенно разные вещи. И как раз стандартное FIFO в UART очень хорошо решает эту проблему, снижая частоту RX-прерываний до 14раз.

 

А может быть, потери в таком случае и не случится? Просто в момент включении DMA будет взведён флажок RXNE, и принятый байт из UARTx->DR благополучно отправится в буфер DMA.

Наверное это можно достаточно просто проверить - принять байт, не вычитывая его, и затем включить DMA.

Потеря может быть не в момент включения, а в момент сброса DMA. Если, как пишет автор, проверить наличие данных в DMA, потом его сбросить, то если байт пришёл между проверкой и сбросом и не успел записаться в память, то он потеряется. Здесь никогда нельзя делать сброс DMA, можно делать только его запрет с последующим разрешением в новый буфер. И если уж работаем через DMA, то только так - тогда никаких обращений к регистру DR UART программно. Всегда нужно помнить: если у канала DMA есть FIFO, то после запрета канала, там могут остаться данные считанные с периферии но не записанные в память.

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


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

Уважаемый jcxz,

Назвал буфер ДМА стеком, ну и что - все поняли кроме вас. Если вы такой хороший программист - напишите драйвер и выложите на суд общественности, а не придирайтесь в словам лишь бы выглядеть умнее.

14 уровневый буфер на USART на сколько я понимаю не снизит частоту возникновений прерываний в 14 раз. А почему должен?

Если как вы предлагаете переключать на новый буфер, то могут произойти потери при переключении буферов, тем более переключить буферы нельзя если не выключить ДМА (по крайней ере так в STM32).

 

Есть еще вариант, как можно отработать прерывание IDLE от USART:

- Считать все байты в дугой буфер

- Проверить не нападало ли новых данных и если нападало - выйти без действий

- Если данные не нападало - просто отключить триггер ДМА, сбросить ДМА, проверить RXNE и вытащить из него байт если он там образовался

- Включить триггер ДМА

В данном случае у нас времени на операцию сброса ДМА ~100мкс, на частоте 115200, что практически гарантирует защиту от сбоя.

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


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

Потеря может быть не в момент включения, а в момент сброса DMA. Если, как пишет автор, проверить наличие данных в DMA, потом его сбросить, то если байт пришёл между проверкой и сбросом и не успел записаться в память, то он потеряется. Здесь никогда нельзя делать сброс DMA, можно делать только его запрет с последующим разрешением в новый буфер.

Ну так, собственно, сброс - это и есть запрет с последующим разрешением. Не думаете же вы, что кто-то в здравом уме будет делать reset периферийного устройства посреди его работы? От запрета данные не теряются, просто замораживается работа. Запрещаем работу DMA (сбросом бита EN), забираем данные, перенастраиваем указатели, включаем DMA. Если за это время придёт байт в UART, то он не потеряется, а будет принят в новый буфер сразу после включения DMA.

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


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

Ну так, собственно, сброс - это и есть запрет с последующим разрешением. Не думаете же вы, что кто-то в здравом уме будет делать reset периферийного устройства посреди его работы?
Я также думал что никто в здравом уме не будет называть запрет (останов) чего-либо сбросом, а стек - FIFO-буфером :laughing:

От запрета данные не теряются, просто замораживается работа. Запрещаем работу DMA (сбросом бита EN), забираем данные, перенастраиваем указатели, включаем DMA. Если за это время придёт байт в UART, то он не потеряется, а будет принят в новый буфер сразу после включения DMA.
Именно о таком алгоритме я и говорил. И при этом не должно быть никаких посторонних доступов к приёмному буферу UART помимо DMA, даже когда DMA запрещён.

 

14 уровневый буфер на USART на сколько я понимаю не снизит частоту возникновений прерываний в 14 раз. А почему должен?
Знаете как работает обыкновенный FIFO UART на других CPU? Он генерит прерывание при достижения метки заполнения буфера (максимум==14байт) или при паузе в приёмном потоке более чем сколько-то бит.

 

Если как вы предлагаете переключать на новый буфер, то могут произойти потери при переключении буферов, тем более переключить буферы нельзя если не выключить ДМА (по крайней ере так в STM32).
А я что писал?

 

Есть еще вариант, как можно отработать прерывание IDLE от USART:

- Считать все байты в дугой буфер

- Проверить не нападало ли новых данных и если нападало - выйти без действий

- Если данные не нападало - просто отключить триггер ДМА, сбросить ДМА, проверить RXNE и вытащить из него байт если он там образовался

- Включить триггер ДМА

В данном случае у нас времени на операцию сброса ДМА ~100мкс, на частоте 115200, что практически гарантирует защиту от сбоя.

В Вашем алгоритме я вижу много дыр, но по-моему объяснять бесполезно..... :smile3046:

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


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

Да, я FIFO назвал стеком, предайте анафеме меня. Что за глупые придирки к словам?

Вы видите много дыр, у вас полна голова знаний - так вы возьмите, прочтите названия темы и скажите как надо сделать а еще лучше - выложите код, как просит автор, а уж мы покритикуем:

Можно ли на STM32F сделать чтение данных из UART в программный буфер FIFO через DMA? Размер принимаемых данных - произвольный, от 1 байта, поток от модема. Киньте примером пожалуйста, если есть опыт подобной реализации.

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

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

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


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

Я ещё в самом первом своём посте в эту тему написал, что не работаю на STM32. И там же предложил алгоритм работы в случае IDLE-прерывания.

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


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

Я также думал что никто в здравом уме не будет называть запрет (останов) чего-либо сбросом, а стек - FIFO-буфером :laughing:

Хватит уже придираться к словам. По алгоритму вопросы остались?

 

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


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

У меня - нет.

Ещё на первое своё сообщение я получил ответы которые меня удовлетворили.

...относительно :)

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


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

Не могу никак запустить UART1 DMA на прием.

По прерываниям прием работает, передача по DMA работает.

Где ошибся не могу найти

 

uint8_t mybuf[256];
void WiFi_Uart_DMA_Rx_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;

/* USART1 RX DMA1 Channe5 */
DMA_DeInit(DMA1_Channel5);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);//0x40013804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)mybuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(mybuf);
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_MemoryInc = ENABLE;
DMA_InitStructure.DMA_PeripheralInc = DISABLE;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel5, DMA_IT_HT | DMA_IT_TC | DMA_IT_TE, DISABLE);

USART_DMACmd(USART1, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);

DMA_Cmd(DMA1_Channel5, ENABLE);
}

void WiFi_UartInit(uint32_t baudrate)
//void InitUart1(void)
{
USART_InitTypeDef 	USART_InitStructure;
GPIO_InitTypeDef 	GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

Uart1BufInit();

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // PA.09 USART1.TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA.10 USART1.RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//  /* Configure the NVIC Preemption Priority Bits */
//	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//
//	/* Enable the USARTy Interrupt */
//	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//	NVIC_Init(&NVIC_InitStructure);

USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1, &USART_InitStructure);

//	/* Enable USARTy Receive and Transmit interrupts */
//	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

USART_Cmd(USART1, ENABLE);

WiFi_Uart_DMA_Rx_Config();
}

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


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

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

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

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

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

×
×
  • Создать...