Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: sam3x SSC + DMA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
nvn
Добрый день!

Есть sam3x4c, к нему подключен кодек tlv320aic3101 по SSC.
Сгенерил табличку синуса в буфер и вручную в цикле выдал её на кодек... все ок.
Попробовал передать буфер с синусом через DMA, тоже все ок, попробовал несколько связанных буферов (Linked List Item), тоже получилось, закольцевал два буфера, получил генератор все работает согласно описанию.
Требуется принимать пакеты RTP по Ethernet и выплевывать их в кодек, раньше пользовал sam7x там использовал PDC контроллер у SSC и все получалось просто, пока передавался первый буфер, по прерыванию видел что второй буфер пуст и подкачивал второй. А здесь не могу сообразить как организовать что-то подобное. Здесь не могу засинхронизироваться, непонятно какой из буферов передался, пробовал разные способы, но щелчки идут...
Может кто делал что-то подобное? В принципе не суть что из Etherneta можно и с microSD файл проиграть, так же ведь нужно подкачивать данные?
Может примеры есть или на проекты наталкивались?
У атмела находил примеры, но там просто подготавливаются 2 или 3 буфера и передаются, после чего остановка, а как сделать именно с подкачкой?

З.Ы. как то наталкивался в инете еще работая на sam7x на проект sam3x8 в связке с кодеком WM8731 (вроде) по DMA и там еще вроде fft была, так сейчас перерыл весь инет, а найти не могу.
aaarrr
Цитата(nvn @ Sep 23 2016, 00:01) *
Здесь не могу засинхронизироваться, непонятно какой из буферов передался, пробовал разные способы, но щелчки идут...

Не очень понимаю причину затруднения. Алгоритм работы примерно такой:
1. Подготовили кольцевой список из N буферов, загрузили в них данные
2. Разрешили прерывание BTC дла канала, запустили DMA
3. По прерыванию отдаем очередной освободившийся (CTRLA.DONE = 1) буфер под загрузку
nvn
Уважаемый, 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?
aaarrr
Цитата(nvn @ Sep 23 2016, 09:20) *
Правильно ли я понимаю, что прерывание возникает когда последний байт буфера отправлен в FIFO, т.е. фактически еще идет его передача?

Совершенно верно.

Цитата(nvn @ Sep 23 2016, 09:20) *
Как определить в прерывании, какой буфер передан и с ним связанно данное прерывание? Самому вести счет?

Да, вести счет. Вы всегда знаете, какой буфер был передан DMA первым, соответственно, он же первым и освободится.

Цитата(nvn @ Sep 23 2016, 09:20) *
Я должен установить CFG.SOD = 1, а в CTRLA.DONE = 0, и когда буфер будет передан DMAC установит CTRLA.DONE = 1 ? И если я не сброшу CTRLA.DONE = 0, то когда CTRLA.DONE во всех буферах станут равными 1 DMAC завершит передачу, и в результате возникнет прерывание CBTC?

Да, в этом случае DMA остановится. Насчет прерывания только не уверен, но по логике должно быть.

Цитата(nvn @ Sep 23 2016, 09:20) *
Где можно почитать более подробно про работу DMAC? Интересуют такие моменты как KEEP, SUSP и ENA в DMAC_CHER, и как их использовать.

Тут не подскажу: я пользовался только мануалом на SAM3U от 11 года, и примерно тогда же последний раз его программировал.
Но для реализации работы с кодеком эти биты не понадобятся sm.gif

Цитата(nvn @ Sep 23 2016, 09:20) *
Принцип работы DMAC одинаков для всех Cortex-M3?

Общие принципы у всех примерно одинаковы, но реализация разная.
nvn
Немного поэкспериментировал. Появилась ясность работы DMAC.
В описанной выше конфигурации контроллера он при обнаружении следующего дескриптора с DONE=1 останавливается, и если его потом снова активировать через DMAC_CHER.ENAx=1, то он продолжает работу с того же самого места.
С SUSP, RES тоже попробовал, стало понятно.

А вот прерывание CBTC в конце не возникает, как я ожидал, но оно и не нужно в данном случае.

Уважаемый, aaarrr, спасибо за помощь!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.