Вы несколько переводите тему. Например, DMA успел передать только часть данных из буфера, а в это время надо добавить в буфер еще порцию. Как тут поступить?
В этом топике мы обсуждаем использование ДМА на
приём данных по UART-у. Передача дело совсем другое.
А как этому DMA задают, сколько байт надо ему качать, если буфер кольцевой?
В случае приёма размер блока равен размеру буфера.
Пример:
typedef dma_channel<'1'> rx_dma;
volatile uint8_t RxBuffer[400];
uint16_t RxNext, RxFirst;
void InitRxDmaChannel()
{
rx_dma::ResetChannel();
rx_dma::SetAddressControl(DMA_CH_SRCRELOAD_NONE_gc, DMA_CH_SRCDIR_FIXED_gc, DMA_CH_DESTRELOAD_BLOCK_gc, DMA_CH_DESTDIR_INC_gc);
rx_dma::SetTriggerSource(DMA_CH_TRIGSRC_USARTF0_RXC_gc);
rx_dma::SetInterruptLevel(DMA_CH_ERRINTLVL_OFF_gc, DMA_CH_TRNINTLVL_OFF_gc);
rx_dma::SetSrcAddress((uint16_t)&EXT_UART.DATA);
rx_dma::SetDestAddress((uint16_t)RxBuffer);
rx_dma::SetTransferSize(sizeof(RxBuffer));
rx_dma::SetRepeatCount(0);
rx_dma::StartPeripheralTransfer(DMA_CH_BURSTLEN_1BYTE_gc, true);
}
int main()
{
init_board();
ExtUartDriver_t::Init();
InitRxDmaChannel();
sei();
while (1) {
Delay(20);
uint16_t dma_rx_index=rx_dma::GetTrfCnt();
RxNext=sizeof(RxBuffer)-dma_rx_index;
if (RxNext!=RxFirst) { // обработка принятых данных
}
}
}
Ждать завершения операции, чтобы потом дать
DMA следующее задание?
В случае передачи думаю лучше подождать или записать данные в буфер передачи и перенести TxNext (а в прерывании по окончании передачи запустить новый блок данных на отправку).
, или это можно сделать на лету, пролонгировав старое
Пролонгировать просто так не получится - регистры будут скорее всего read only. Значит нужно сбрасывать/запрещать канал. По мне так это как-то некрасиво.