|
|
  |
USART PDC переключение областей памяти, Как переклютать без вероятности потерять байт? |
|
|
|
Apr 2 2008, 18:55
|

Частый гость
 
Группа: Свой
Сообщений: 169
Регистрация: 17-09-07
Из: Красноярск
Пользователь №: 30 600

|
У меня это организовано так: Код void ProcessUpLinkIncomingMessages(void) { unsigned int rcr=pDataLinkPDC->PDC_RCR; if ( rcr==UPLINK_BUFFER_SIZE ) return;
switch (BufferSemaphore) { case PRIMARY:
AT91F_PDC_SetRx(pDataLinkPDC,UpLinkRXBufferSec,UPLINK_BUFFER_SIZE); ProcessMessages (UpLinkRXBufferPri,(unsigned short)(UPLINK_BUFFER_SIZE-rcr),UpLinkPayLoadBuffer, &UpLinkMessageState); BufferSemaphore=SECONDARY;
break; case SECONDARY:
AT91F_PDC_SetRx(pDataLinkPDC,UpLinkRXBufferPri,UPLINK_BUFFER_SIZE); ProcessMessages (UpLinkRXBufferSec, (unsigned short)(UPLINK_BUFFER_SIZE-rcr),UpLinkPayLoadBuffer, &UpLinkMessageState); BufferSemaphore=PRIMARY;
break; }
} Процедура вызывается 100 раз в секунду. Бод рейт 57600, UPLINK_BUFFER_SIZE=256 Пакеты идут плотно, разной длины, проверяется контрольная сумма в конце пакета. Условия "тепличные", пакеты теряются. Хочу исключить (или подтвердить) то опасение, когда байт теряется от переключения буферов. Похорошему нужно задействовать RNPR RNCR, но тут сразу вопрос: как грамотно переключиться обратно на первоначальные счётчики RPR, RCR и не потерять данные ? Или опасения мои пустые вовсе? забыл чип указать: sam7s
Сообщение отредактировал Goofy - Apr 2 2008, 19:10
|
|
|
|
|
Apr 3 2008, 18:16
|

Частый гость
 
Группа: Свой
Сообщений: 169
Регистрация: 17-09-07
Из: Красноярск
Пользователь №: 30 600

|
Цитата(aaarrr @ Apr 3 2008, 03:35)  Опасения пустые: значения из RNPR и RNCR копируются в RPR и RCR автоматом, т.е. в прерывании по ENDRX нужно просто записать данные нового буфера в RNPR и RNCR. Спасибо за информацию! Стабильность возросла, но ликвидирована не последняя причина потерь пакетов. Решил обойтись без прерывания, PDC пишет всегда в один буфер, перескакивая на его начало, обработка "догоняет" запись при каждом вызове: Код if (pPDC->PDC_RNCR) { // same buffer session if (BytesLeft>rcr) ProcessMessages (RXBufferPri+(BUFFER_SIZE-BytesLeft),(BytesLeft-rcr),PayLoadBuffer, &MessageState); BytesLeft=rcr; } else { //new one ProcessMessages (RXBufferPri+(BUFFER_SIZE-BytesLeft), BytesLeftFromPast ,PayLoadBuffer, &MessageState); AT91F_PDC_SetNextRx (pPDC,RXBufferPri,_BUFFER_SIZE); BytesLeft=BUFFER_SIZE; }
|
|
|
|
|
Apr 3 2008, 18:44
|

Частый гость
 
Группа: Свой
Сообщений: 169
Регистрация: 17-09-07
Из: Красноярск
Пользователь №: 30 600

|
Цитата(aaarrr @ Apr 4 2008, 02:28)  ИМХО, очень странный метод работы. Чем прерывания-то не угодили? Данный код достаточен. Достаточен в тех условиях что буффер не заполнится гарантировано между вызовами. А если достаточен зачем делать больше?...
|
|
|
|
|
Apr 3 2008, 22:12
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(sergeeff @ Apr 3 2008, 21:22)  Теперь по делу. Если не секрет - что за процессор? Не с кэшом ли часом? SAM7S см. самый первый пост. Цитата Данный код достаточен. раз теряются данные, то видать недостаточен. Я поступил бы так: По прерыванию DMA, постановка текущего принятого буфера в очередь на обработку, там же в прерывании выделение буфера для сл. пакета и подзагрузка DMA next указателя. В основном теле программы - проверка очереди пакетов, обработка и освобождение.
|
|
|
|
|
Apr 4 2008, 04:56
|

Частый гость
 
Группа: Свой
Сообщений: 169
Регистрация: 17-09-07
Из: Красноярск
Пользователь №: 30 600

|
Цитата(defunct @ Apr 4 2008, 06:12)  SAM7S см. самый первый пост. раз теряются данные, то видать недостаточен.
Я поступил бы так: По прерыванию DMA, постановка текущего принятого буфера в очередь на обработку, там же в прерывании выделение буфера для сл. пакета и подзагрузка DMA next указателя.
В основном теле программы - проверка очереди пакетов, обработка и освобождение. Теряются пакеты из за других косяков. А именно когда идут пакеты разного типа. Когда идёт один тип, всё отлично (очевидно проблемы в обработке) Второй буфер заполняется, но фактически это тот же адрес. То есть циклически пишем в один и тот же буффер обрабатывая поступающие данные в догонку убывающему RCR. Нет нужды в прерываниях, лишних массивах, аллоцировании памяти, флагах заполнения вот подкорректированый код, если внимательно посмотреть, ряд вопросов пропадёт Код { if (!pPDC->PDC_RNCR) //Анализируется, не выполнено ли первоначальное заполнение буфера, когда RNCR обнулиться. //Если да, то дочитывается "хвост" образовавшийся в момент переключения PDC c RPR на RNPR, нопроцедурой не обработанный
{ ProcessMessages (RXBufferPri+(BUFFER_SIZE-BytesLeft), BytesLeft ,PayLoadBuffer, &GPSMessageState); //назначается следующий принимающий буффер (те же адреса уже обрабатываются в RPR и RCR) AT91F_PDC_SetNextRx (pPDC,RXBufferPri,BUFFER_SIZE); //не SetRx! BytesLeft=BUFFER_SIZE; //сбрасывается число недочитанных байт
}
//Если чило оставшихся непрочитанных байт BytesLeft меньше числа записанных rcr // то обрабатываем разницу с соответсвующим смещением if (BytesLeft>rcr) ProcessMessages (RXBufferPri+(BUFFER_SIZE-BytesLeft),(BytesLeft-rcr),PayLoadBuffer, &MessageState); BytesLeft=rcr;
} частота вызова строго 100Гц размер буфера 256 при бод рейте 57600 наложение ещё не прочитанных данных вновь пришедшими исключено
Сообщение отредактировал Goofy - Apr 4 2008, 05:11
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|