Вот накушался. Может кому-то спасет много времени.
Вводная: копался с XModem Service... надо было передать по XModem маленький файлик размером не более 528 байт (страница dataflash). вобщем и частном можно рассматривать пример
AT91RM9200-BasicROM_Services-ARM1_2-2_0.zip.
все вроде бы хорошо (акцентирую внимание на нужных кусках кода):
Код
AT91S_SBuffer sXmBuffer;
AT91S_Pipe xmodemPipe;
AT91S_SvcXmodem svcXmodem;
// "Tempo" Service
AT91S_CtlTempo ctlTempo;
.....
void AT91_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
{
AT91PS_USART pUsart = svcXmodem.pUsart;
svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);
}
Вроде все логично: сначала tempo сервис от XModem'a используется для посылки "C" ежесекундно, как только начинается прием - он не нужен - соответственно он в дальнейшем используется для ожидания окончания обмена (прихода символа EOT).
Поведение: файлик принимается правильно, но основная прога наглухо застревает в while (EndOfTransmission != 1);
Код
xmodemPipe.Read(&xmodemPipe, (char *) Buffer_Xmodem, MEMORY_SIZE_MAX, AT91_XmodemProtocol, (void *) Buffer_Xmodem);
while (EndOfTransmission != 1);
и не попадает в заветный,
Код
void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
{
// stop the Xmodem tempo
svcXmodem.tempo.Stop(&(svcXmodem.tempo));
// upload complete
EndOfTransmission = 1;
}
который его выведет из этого цикла
А вся фича в том, что при получении прерывания (вызове из IRQ.SYSTEM_INTERRUPT svcXModem.Handler) по приему
символа (RXRDY) - стопорится XModem'овский tempo таймер.
----------------------
xmodemPipe.Read(...)
----------------------
посылка символов "C"
----------------------
INT на символ RXRDY(SOH): svcXModemHandler.Handler (он же svcXModemReadHandler)
остановка svcXModem.tempo
настройка прерываний на PDC
----------------------
...
----------------------
INT PDC: svcXModemHandler.Handler (он же svcXModemReadHandler)
FillRdBuffer()
если принято все что должно было прийти(нет места для приема) - вызов callback (а это заветный AT91_XmodemProtocol), который запускает svcXmodem.tempo!!!!
настройка прерываний на
символ----------------------
INT на
символ (наглядно увидеть EOT):
И вот svcXModem.tempo стопорится. символ EOT пришел, а таймер, который его ждет и хотит об это сообщить в callback, убит этим пришедшим символом.
Далее можно бесконечно ждать while (EndOfTransmission != 1);
(так сказать "мордой об асфальт перед финишной чертой"

)
----------------------
Лекарство:
для ожидания окончания приема добавить в сервис CtlTempo еще один софтовый таймер SvcTempo и его ждать. Самый дешевый и экономный по памяти и по коду способ. (можно еще перекрыть SvcXModem.Handler и отслеживать "чужой" таймер в SvcXModem.tempo... но все это от лукавого)
Код
AT91S_SvcTempo svcTempoWaitX;
....
ctlTempo.CtlTempoCreate(&ctlTempo, &svcTempoWaitX);
...
void AT91_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
{
svcTempoWaitX.Start(&svcTempoWaitX, 10, 0, AT91_XmodemComplete, (void*) 0);
}
void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
{
// не перезагружаемый таймер сам остановится!!!
EndOfTransmission = 1;
}
Все. иду спать