Уважаемый,
aaarrr, прежде всего спасибо за ответ!
Цитата(aaarrr @ Sep 23 2016, 02:38)

Не очень понимаю причину затруднения. Алгоритм работы примерно такой:
1. Подготовили кольцевой список из N буферов, загрузили в них данные
2. Разрешили прерывание BTC дла канала, запустили DMA
3. По прерыванию отдаем очередной освободившийся (CTRLA.DONE = 1) буфер под загрузку
Причина затруднения связана видимо с моим недопониманием работы DMAC.
Вот что я делаю:
CODE
#define DMA_CH 0
void init_dma(void)
{
// ...
dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN);
// ...
/* Set channel configuration register */
cfg = DMAC_CFG_SOD_DISABLE | /* Enable stop on done */
DMAC_CFG_DST_H2SEL | /* Hardware Selection for the Destination */
DMAC_CFG_DST_PER(3) | /* Destination with Peripheral identifier */
DMAC_CFG_AHB_PROT(1) | /* Set AHB Protection */
DMAC_CFG_FIFOCFG_ALAP_CFG; /* FIFO Configuration */
dmac_channel_set_configuration(DMAC, DMA_CH, cfg);
/* Set interrupt */
NVIC_EnableIRQ(DMAC_IRQn);
dmac_enable_interrupt(DMAC, (DMAC_EBCIER_CBTC0 << DMA_CH) | (DMAC_EBCIER_BTC0 << DMA_CH));
}
dma_transfer_descriptor_t desc[2];
void ssc_dma(void *p_buffer1, void *p_buffer2, uint16_t us_size)
{
desc[0].ul_source_addr = (uint32_t)p_buffer1;
desc[0].ul_destination_addr = (uint32_t)(&SSC->SSC_THR);
desc[0].ul_ctrlA = DMAC_CTRLA_BTSIZE(us_size)
| DMAC_CTRLA_SRC_WIDTH_HALF_WORD
| DMAC_CTRLA_DST_WIDTH_HALF_WORD;
desc[0].ul_ctrlB = DMAC_CTRLB_SRC_DSCR_FETCH_FROM_MEM
| DMAC_CTRLB_DST_DSCR_FETCH_FROM_MEM
| DMAC_CTRLB_FC_MEM2PER_DMA_FC
| DMAC_CTRLB_SRC_INCR_INCREMENTING
| DMAC_CTRLB_DST_INCR_FIXED;
//| DMAC_CTRLB_IEN;
desc[0].ul_descriptor_addr = (uint32_t)&desc[1];
desc[1].ul_source_addr = (uint32_t)p_buffer2;
desc[1].ul_destination_addr = (uint32_t)(&SSC->SSC_THR);
desc[1].ul_ctrlA = DMAC_CTRLA_BTSIZE(us_size)
| DMAC_CTRLA_SRC_WIDTH_HALF_WORD
| DMAC_CTRLA_DST_WIDTH_HALF_WORD;
desc[1].ul_ctrlB = DMAC_CTRLB_SRC_DSCR_FETCH_FROM_MEM
| DMAC_CTRLB_DST_DSCR_FETCH_FROM_MEM
| DMAC_CTRLB_FC_MEM2PER_DMA_FC
| DMAC_CTRLB_SRC_INCR_INCREMENTING
| DMAC_CTRLB_DST_INCR_FIXED;
//| DMAC_CTRLB_IEN;
desc[1].ul_descriptor_addr = (uint32_t)&desc[0];
dmac_channel_multi_buf_transfer_init(DMAC, DMA_CH, &desc[0]);
/* Start DMA transfer */
dmac_channel_enable(DMAC, DMA_CH);
/* Enable SSC transmitter */
ssc_enable_tx(SSC);
}
void DMAC_IRQHandler(void)
{
uint32_t dma_status;
dma_status = dmac_get_status(DMAC);
TST_ON;
if (dma_status & (DMAC_EBCIER_BTC0 << DMA_CH)) {
}
if (dma_status & (DMAC_EBCIER_CBTC0 << DMA_CH)) {
}
TST_OFF;
}
В результате получаю бесконечную передачу буферов по кольцу. Получаю также постоянные периодические прерывания BTC.
Правильно ли я понимаю, что прерывание возникает когда последний байт буфера отправлен в FIFO, т.е. фактически еще идет его передача? При этом DMAC уже считал следующий дескриптор (потому что я пробовал занулить в прерывании BTC desc[1].ul_descriptor_addr =0; и в результате было четыре передачи).
Как определить в прерывании, какой буфер передан и с ним связанно данное прерывание? Самому вести счет?
Цитата(aaarrr @ Sep 23 2016, 02:38)

3. По прерыванию отдаем очередной освободившийся (CTRLA.DONE = 1) буфер под загрузку
Не могу понять как работает этот (CTRLA.DONE = 1).
Я должен установить CFG.SOD = 1, а в CTRLA.DONE = 0, и когда буфер будет передан DMAC установит CTRLA.DONE = 1 ? И если я не сброшу CTRLA.DONE = 0, то когда CTRLA.DONE во всех буферах станут равными 1 DMAC завершит передачу, и в результате возникнет прерывание CBTC?
Где можно почитать более подробно про работу DMAC? Интересуют такие моменты как KEEP, SUSP и ENA в DMAC_CHER, и как их использовать.
Принцип работы DMAC одинаков для всех Cortex-M3?