Цитата(mantech @ Apr 16 2015, 10:59)

Это только в "тепличных" условиях. В моем случае была поддержка протоколов с пакетами разной длины от 6 до 1000 байт, причем длина указывается в первых байтах, без таймаутов, там же и ИД-пакета, которые нужно парсить "на лету", тут все фифы только вредят, и работа уартов на 115200 не сильно замедляет систему, если конечно, не нагружать прерывания чем-то еще, кроме приема...
Ну да... 11520*6UART*2(TX/RX) итого частота прерываний ==138240Гц, т.е. - прерывания с периодом 7.2мкс конечно не нагружают никак систему

Про случай когда надо работать всего с одним UART-ом - тут нет вопросов.
А ведь бывают ещё и бОльшие скорости по UART.
У нас тоже по всем UART-каналам идёт обмен по протоколам с размером кадров переменной длины. FIFO не мешает этому никак.
Цитата(SasaVitebsk @ Apr 16 2015, 11:05)

Плюс поясните мне пожалуйста. Вот я записываю информацию во флэшку. Потом мне надо ждать готовности флэшки. Как это обойти с помощью DMA?
Когда нужно всего пару байт - никто не мешает использовать обмен по прерываниям: записать в FIFO сразу все 1...8 слов, а потом получить 1..N прерываний и вычитать.
Можно комбинировать (я так делаю при малых размерах транзакции по SPI, полностью влезающей в размер FIFO): настраиваю DMA только на приёмный канал, записываю в TX.FIFO сразу все байты (программно), а потом по окончании приёма всего пакета получаю ОДНО прерывание завершения DMA (без ожидания таймаута по завершению).
Готовность AT45DB никак не надо обходить. Считывать регистр состояния согласно документации. Хоть программно, хоть с DMA.
Никто не мешает смешивать работу через DMA с программным обменом, хоть одновременно, хоть поочередно.
В зависимости от SCLK и её соотношения с частотой CPU, можно хоть программно записать в SPI необходимую команду чтения статуса и ждать поллингом завершения приёма
(допустимо при большой SCLK, когда такое ожидание приёма занимает мало тактов и выигрыш от освобождения процессора на время передачи невелик или нету его),
хоть записать программно, настроив DMA на приём ответа и генерацию прерывания по завершению (если SCLK много меньше частоты CPU и если ждать поллингом, то
надолго займёшь CPU впустую).
На МК без FIFO всё гораздо хуже, так как нельзя записать целиком посылку в FIFO, настроив только RX.DMA.
Мы много используем AT45DB. Передача данных в драйверах идёт через DMA, опрос состояния - как я описал (у нас SCLK=25...30МГц).
Под рукой сейчас нет исходника с AT45DB, но вот подобная операция с nRF24L01+ (чтение регистра nRF24L01+ - короткая SPI-транзакция):
CODE
static void ActSSP(int cmd, int len, int stepNew)
{
Pclr(PIN_NRF_CS); //CS=low
isrStep = stepNew;
volatile HwRegsSSP *ssp = &concatAB(SSP, nSSP_nrf);
HwRegsDMA::T_CH volatile *ch = &DMA.CH[DMA_CH_nrf_RX];
//DMA-канал DMA_CH_nrf_RX статически привязан к данному SPI (nSSP_nrf), так что адрес источника (ch->SRC) и ch->LLI устанавливаются в инит-коде и каждый раз их писать не надо.
//Всё программирование DMA для запуска транзакции занимает 3 строчки кода ниже, настройка регистров: ch->DST, ch->CTL и старт RX.DMA: ch->CFG.
ch->DST = &sh.regIO.status;
ch->CTL = len + sizeof(sh.regIO.status) | 1 << 12 | B27 | B31;
ch->CFG = B0 | (DMA_REQ_nrf_RX >> 4) << 1 | 2 << 11 | B14 | B15;
ssp->CR[1] = B1; //включаем SPI-канал
__DMB();
ssp->DR = cmd; //старт передачи (и приёма)
}
static uint RegRead(REG reg)
{
ActSSP((int)reg + CMD_R_REGISTER, 1, IS_GAP);
concatAB(SSP, nSSP_nrf).DR = 0; //запись хвоста (для приёма значения регистра)
NrfCtxSw(); //переключение контекста в фоновую задачу с ожиданием завершающего DMA-IRQ, который делает CS=high
return sh.regIO.val[0];
}
Код
#define concatAB_(a, b) a##b
#define concatAB(a, b) concatAB_(a, b)
Это код для LPC17xx.