|
|
  |
DMAC + SSP на STR912, полный ступор... |
|
|
|
Jan 2 2008, 01:36
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Пытаюсь переписать функции для работы с MMC картой для работы через DMA Полный ноль. Для начала, как я понимаю, запрос на ДМА воникает при приеме данных. Чтобы что-то принять нужно что-то передать. Настраиваю один канал на прием, второй на передачу. Как запустить передачу? Сигнал SSP TX постоянно активен, пока не заполнено FIFO? Или надо произвести какие-то телодвижения, чтобы запустить передачу? Пока имею такой код. ДМА не запускается, код ничего никуда не грузит... Код DMA_InitTypeDef DMA_InitStruct; DMA_ChannelCmd(DMA_Channel0, DISABLE); // Disable the DMA channel DMA_ChannelCmd(DMA_Channel1, DISABLE); // Disable the DMA channel /* RECIVE */ DMA_StructInit(&DMA_InitStruct);
/* Write the first LLI*/ DMA_InitStruct.DMA_Channel_LLstItm = 0; // Set the addresses of next linked list for the first LLI structure DMA_InitStruct.DMA_Channel_SrcAdd = (u32)&(SSP0->DR); // source address for the first LLI structure DMA_InitStruct.DMA_Channel_DesAdd = (u32)pData; // Destination address for the first LLI structure DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte; // The source bus width is a byte DMA_InitStruct.DMA_Channel_DesWidth = DMA_SrcWidth_Byte; // The Destination bus width is a byte DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl_Perip2;// DMA is The flow controller DMA_InitStruct.DMA_Channel_TrsfSize = 512; // Transfer size DMA_InitStruct.DMA_Channel_Src = DMA_SRC_SSP0_RX; // Chanel source
/* Configure the DMA channel1 "the chosen channel to perform the transfer" */
DMA_ChannelSRCIncConfig (DMA_Channel0, DISABLE); DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE); DMA_SyncConfig(0, ENABLE);
DMA_Init(DMA_Channel0,&DMA_InitStruct); // update the DMA channel1 registers with the cfirst LLI structure /* TRANSFER */ DMA_StructInit(&DMA_InitStruct);
/* Write the first LLI*/ DMA_InitStruct.DMA_Channel_LLstItm = 0; // Set the addresses of next linked list for the first LLI structure DMA_InitStruct.DMA_Channel_SrcAdd = (u32)pData; // source address for the first LLI structure DMA_InitStruct.DMA_Channel_DesAdd = (u32)&(SSP0->DR); // Destination address for the first LLI structure DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte; // The source bus width is a byte DMA_InitStruct.DMA_Channel_DesWidth = DMA_SrcWidth_Byte; // The Destination bus width is a byte DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl_Perip1;// DMA is The flow controller DMA_InitStruct.DMA_Channel_TrsfSize = 512; // Transfer size DMA_InitStruct.DMA_Channel_Src = DMA_DES_SSP0_TX; // Chanel destination
/* Configure the DMA channel1 "the chosen channel to perform the transfer" */
DMA_ChannelSRCIncConfig(DMA_Channel1, ENABLE); DMA_ChannelDESIncConfig(DMA_Channel1, DISABLE); DMA_SyncConfig(1, ENABLE);
DMA_Init(DMA_Channel1,&DMA_InitStruct); // update the DMA channel1 registers with the cfirst LLI structure DMA_ChannelCmd(DMA_Channel0,ENABLE); // Enable the DMA channel DMA_ChannelCmd(DMA_Channel1,ENABLE); // Enable the DMA channel
/*wait for the fifo to be empty*/ while(DMA_GetChannelActiveStatus(DMA_Channel1));
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Jan 2 2008, 06:58
|

Частый гость
 
Группа: Свой
Сообщений: 93
Регистрация: 5-03-06
Из: Украина, Киев
Пользователь №: 14 970

|
Цитата(Dron_Gus @ Jan 2 2008, 03:36)  Как запустить передачу? Сигнал SSP TX постоянно активен, пока не заполнено FIFO? Или надо произвести какие-то телодвижения, чтобы запустить передачу? Как я понимаю, после настройки SSP в режиме Мастер передача должна начаться, сразу после того, как Вы положите байт в TX FIFO. По окончанию передачи ( когда FIFO пусто ) будет интерапт, и можно проверить буфер приёма и послать следующий байт. Это если я все правильно понимаю.  Если так оно не работает, то смотрите на настройки SSP.
|
|
|
|
|
Jan 3 2008, 00:08
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Код void MmcReceiveBlock (pInt8U pData, Int32U Size) { char SSP_WriteByte = 0xff; DMA_InitTypeDef DMA_InitStruct; /* Enable FIFO */ SSP_DMACmd(SSP0, SSP_DMA_Receive, ENABLE); SSP_DMACmd(SSP0, SSP_DMA_Transmit, ENABLE); /* RECIVE - DMA ch 0 */ DMA_StructInit(&DMA_InitStruct); /*No linked lists used*/ DMA_InitStruct.DMA_Channel_LLstItm = 0; /*Source address*/ DMA_InitStruct.DMA_Channel_SrcAdd = (u32)(&SSP0->DR); /*Destination address*/ DMA_InitStruct.DMA_Channel_DesAdd = (u32)pData; /*Source width of one byte*/ DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte; /*DMA burst size of 4 data*/ DMA_InitStruct.DMA_Channel_SrcBstSize = DMA_SrcBst_4Data; /*Destination width of one byte*/ DMA_InitStruct.DMA_Channel_DesWidth = DMA_DesWidth_Byte; /*The flow controller is the DMAC*/ DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl2_DMA; /* DMA req source */ DMA_InitStruct.DMA_Channel_Src = DMA_SRC_SSP0_RX; /*Transfer size */ DMA_InitStruct.DMA_Channel_TrsfSize = Size; /*We increment the destination not the source */ DMA_ChannelSRCIncConfig (DMA_Channel0, DISABLE); DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE); /* Init */ DMA_Init(DMA_Channel0, &DMA_InitStruct); /* TRANSFER - DMA ch 1 */ DMA_StructInit(&DMA_InitStruct); /*No linked lists used*/ DMA_InitStruct.DMA_Channel_LLstItm = 0; /*Source address*/ DMA_InitStruct.DMA_Channel_SrcAdd = (u32)&SSP_WriteByte; /*Destination address*/ DMA_InitStruct.DMA_Channel_DesAdd = (u32)((&SSP0->DR)); /*Source width of one byte*/ DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte; /*Destination width of one byte*/ DMA_InitStruct.DMA_Channel_DesWidth = DMA_DesWidth_Byte; /*The flow controller is the DMAC*/ DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl1_DMA; DMA_InitStruct.DMA_Channel_Des = DMA_DES_SSP0_TX; /*Transfer size */ DMA_InitStruct.DMA_Channel_TrsfSize = Size; /*We increment not the source not the destination*/ DMA_ChannelSRCIncConfig (DMA_Channel1, DISABLE); DMA_ChannelDESIncConfig (DMA_Channel1, DISABLE); /* Init */ DMA_Init(DMA_Channel1, &DMA_InitStruct); /* Start transfer */ DMA_ChannelCmd(DMA_Channel0, ENABLE); DMA_ChannelCmd(DMA_Channel1, ENABLE); /* wait for the transmit channel FIFO to be empty */ while(DMA_GetChannelActiveStatus(DMA_Channel1)); /* wait for the recive channel FIFO to be empty */ while(DMA_GetChannelActiveStatus(DMA_Channel0)); Рабочий код. Производительность не мерил, но с ним уже удается без остановки "кормить" двухканальный PWM wav-файлом (44100 16 x 2) через EFSL. Это апримерно 176 Кбайт/сек. В два раза ускоряю - уже не вытягивает. На всяк случай косяки на которые я наступил: DMA на прием запускается не сразу - поэтому ловить его остановку стоит только после остановки DMA на передачу, иначе можем выскочить из функции еще до того, как DMA на прем принял хоть байт. На сайте ST есть прмеры DMA под многие периферии. Правда примеров с одновременной передачей-приемом нет. З.Ы. от шумов (потрескивания) PWM можно как-нить избавиться? Сейчас на выходе стоит цепочка (резистор)-(кондер на землю)-(резистор)-(кондер на землю). Противно посчелкивает сразу же после включения PWM.
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Jan 3 2008, 13:02
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Цитата(AlexandrY @ Jan 3 2008, 09:24)  К сожалению не могу помочь вам решить проблему используя либы от ST. Да, либы их малость "монстроидальные". Смысла их пользовать нет. Цитата(AlexandrY @ Jan 3 2008, 09:24)  Но по ссылке есть пакет примеров для STR91x c DMA и для SD карт и для аудиокодека. Спасибо огромное, уже изучаю. Как раз стоит задача прикрутить TLV320AIC к STR912. Что-то мне подсказывает, что это не реально...
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Jan 11 2008, 18:13
|
Местный
  
Группа: Свой
Сообщений: 251
Регистрация: 26-07-05
Пользователь №: 7 117

|
Цитата(Dron_Gus @ Jan 3 2008, 16:02)  Да, либы их малость "монстроидальные". Смысла их пользовать нет.
Спасибо огромное, уже изучаю. Как раз стоит задача прикрутить TLV320AIC к STR912. Что-то мне подсказывает, что это не реально... TLV320AIC10 прекрасно пашет с str911, кодек работает мастером - так проще.
|
|
|
|
|
Jan 12 2008, 23:45
|
Участник

Группа: Свой
Сообщений: 51
Регистрация: 20-07-04
Пользователь №: 342

|
У меня DMA и SSP удалось подружить всё работает, единственно что третий канал DMA с прерыванием не удалось подружить. привожу фрагменты кода "как есть". ============================================== последовательность програмироания при инициализации
Init_SSP0_fast_DMA() --------------------------------------- SSP0->CR0 = 0xxxxx; // параметры ssp по месту SSP0->CR1 = 0xxx; SSP0->PR = 0xxx; SSP0->IMSCR = 0x04; /* SSP0 Inerrupt enable: RXIM - receive */ SSP0->ICR = 0x00; /* SSP0 Inerrupt clear */ SSP0->DMACR = 0x03; /* SSP0 DMA control - Transmit */ ----------------------------------------------------
SSP0_enable(); ---------------------------------------------------- k = SSP0->DR; /* byte 1 load 8 byte only Read */ k = SSP0->DR; /* byte 2 load 8 byte only Read */ k = SSP0->DR; /* byte 3 load 8 byte only Read */ k = SSP0->DR; /* byte 4 load 8 byte only Read */ k = SSP0->DR; /* byte 5 load 8 byte only Read */ k = SSP0->DR; /* byte 6 load 8 byte only Read */ k = SSP0->DR; /* byte 7 load 8 byte only Read */ k = SSP0->DR; /* byte 8 load 8 byte only Read */
SSP0->ICR = 0x03; // clear IRQ SSP0->CR1 |= 0x02; ----------------------------------------------------
Init_DMA_IRQ (); ---------------------------------------------------- VIC0->VAiR[12] = (unsigned int)DMA_IRQ_Handler; /* Setup DMA IRQ Hndl addr */ VIC0->VCiR[12] |= 12; /* Specify the interrupt number */ VIC0->VCiR[12] |= 0x20; /* Enable the vector interrupt */ VIC0->INTER |= (1<<12); /* Enable SSP0 interrupt */ ----------------------------------------------------
Init_DMA_5_6_7 (); ---------------------------------------------------- DMA->SYNR = 0x00; /* SYNC = 0 enable */ DMA->CNFR = 0x01; /* EN = 1 enable DMA */ /* ------------ INIT DMA CHANEL 5 SPI_0 Resiver ------------------------------------------*/ DMA_Channel5->SRC = 0x4C007008; /* DMA-5 Source Address SSP0_DR */ DMA_Channel5->DES = (u32)(&bufer[3]); /* DMA-5 Destination Address + 4; 4000000 - RAM */ DMA_Channel5->LLI = 0; /* DMA-5 LLI => 0 */ DMA_Channel5->CC = 0xE80003A1; /* interrupt enable, cacheable, bufferable, */ /* INC dst, DWIDTH = 8 bit, SWIDTH = 8 bit, */ /* DBsize = 1 byte, SBsize = 1 byte, N -= 4 ... */ DMA_Channel5->CCNF = 0x00009358; /* interrupt enable, periph-mem DMA, ok */ /* SrcPeriph = SSP_0 RX */ /* ------------ INIT DMA CHANEL 6 SPI_0 Transmit -----------------------------------------*/ DMA_Channel6->SRC = (u32)(&bufer[3]); /* DMA-6 Source Address + 4; 4000000 - RAM */ DMA_Channel6->DES = 0x4C007008; /* DMA-6 Destination Address SSP0_DR */ DMA_Channel6->LLI = 0; /* DMA-6 LLI => Link[0] */ DMA_Channel6->CC = 0xE40003A1; /* interrupt enable, cacheable, bufferable, ok */ /* INC src, DWIDTH = 8 bit, SWIDTH = 8 bit, */ /* DBsize = 1 byte, SBsize = 1 byte, N -= 4 ... */ DMA_Channel6->CCNF = 0x00000B58; /* interrupt disable, mem-periph DMA, not IRQ */ /* DstPeriph = SSP_0 TX N = BAH = 186 - max */ /* ------------ INIT DMA CHANEL 7 Memory to Memory ---------------------------------------*/ DMA_Channel7->SRC = (u32)(&bufer[0]); /* DMA-7 Source Address kadr_bufer - RAM */ DMA_Channel7->DES = (u32)(&e_bufer[0]); /* DMA-7 Destination Address picture_bufer */ DMA_Channel7->LLI = 0; /* DMA-7 LLI => Link[0] */ DMA_Channel7->CC = 0xCC4800E9; /* interrupt enable, INC dst, INC src, */ /* DWIDTH = 32 bit, SWIDTH = 32 bit, */ /* DBsize = 0, SBsize = 0, N = E9 = 233 (*4) */ DMA_Channel7->CCNF = 0x00000084; /* interrupt disable, mem-mem DMA, */ ----------------------------------------------------
Init_DMA_4 (); ---------------------------------------------------- /* ------------ RE_INIT DMA CHANEL 7 Mem to Mem copy -----------------------------------*/ DMA_Channel4->SRC = (u32)(&bufer[0]); /* DMA-7 Source Address bufer - RAM */ DMA_Channel4->DES = (u32)(&e_bufer[0]); /* DMA-7 Destination Address e_bufer */ DMA_Channel4->LLI = 0; /* DMA-7 LLI => Link[0] */ DMA_Channel4->CC = 0xCC4800E9; /* interrupt enable, INC dst, INC src, */ DMA_Channel4->CCNF = 0x00000084; /* interrupt disable, mem-mem DMA, */ ----------------------------------------------------
Enable_DMA (); ---------------------------------------------------- DMA_Channel7->CCNF |= 0x01; /* DMA enable */
----------------------------------------------------
Chip_SPI_Reset();
и далее по тексту.... ========================================== В самой программе необходимо обеспечить старт а затем всё будет обеспечиваться самим DMA DMA_Channel5->CCNF |= 0x00000001; /* DMA-5 SPI_0 reseive START */ DMA_Channel6->CCNF |= 0x00000001; //
============================================================================ ============================================================================ DMA_IRQ_Handler
PUSH {R0-R3,LR} ;-------- control chanel 5 & 6 --------------------- LDR R0,=DMA_BASE ; =DMA_BASE ; MOV R1,#0x00000060 ;-------- Chanel 5 & 6 ----------------------------- STR R1,[R0,#0x08] ; clear Terminal Count Interrupt 5 & 6 ;-------- DMA -------------------------------------- LDR R2,=DMA_CC5_init ; STR R2,[R0,#DMA_CC5] ; DMA_CC5
LDR R2,=DMA_CC6_init ; STR R2,[R0,#DMA_CC6] ; DMA_CC6
MOV R2,#0 ; LLI = 0 STR R2,[R0,#DMA_LLI5] ; LLI5 = 0 STR R2,[R0,#DMA_LLI6] ; LLI6 = 0 ;-------- update kad ------------------------- LDR R2,=kadr_kadr ; Load adres LDRB R3,[R2,#0] ; Load = kad ADD R3,R3,#1 ; AND R3,R3,#mask_DMA_number_kadr ; STRB R3,[R2,#0] ; save new kad ;-------- new adres bufera ------------------------- LDR R1,=kadr_bufer ; Load adres MOV R2,#size_kadr ; size_kad (offset) MLA R2,R2,R3,R1 ; new adres bufera DST ;-------- program DMA_5_6 ------------------------- STR R2,[R0,#DMA_DEST5] ; DMA_DEST5 STR R2,[R0,#DMA_SRC6] ; DMA_SRC6 ;-------- Ready_Date ------------------------------- LDR R1,=Ready_Date ; Load adres LDRB R2,[R1,#0] ; Load = Ready_Date ADD R2,R2,#1 ; STRB R2,[R1,#0] ; Save = Ready_Date CMP R2,#15 ; BHS Konec_DMA ; if BUSY go to ;-------- start DMA_5_6 ---------------------------- LDR R3,[R0,#DMA_CCNF5] ; chanel 5 RX SSP_0 ORR R3,R3,#0x00000001 ; STR R3,[R0,#DMA_CCNF5] ;
LDR R3,[R0,#DMA_CCNF6] ; chanel 6 TX SSP_0 ORR R3,R3,#0x00000001 ; STR R3,[R0,#DMA_CCNF6] ; Konec_DMA ;-------- END ------------------------------------ MOV R1,#0 ; STR R1,[R1,#-0xfd0] ; MOV R1,#0 ; MOV R2,#0xfc000000 ; STR R1,[R2,#0x30] ; POP {R0-R3,LR} ; SUBS PC,LR,#4 ;
|
|
|
|
|
Jan 15 2008, 11:43
|
Местный
  
Группа: Свой
Сообщений: 251
Регистрация: 26-07-05
Пользователь №: 7 117

|
Цитата(Dron_Gus @ Jan 13 2008, 13:03)  Спасибо! А аппаратно какие сигналы TLV320AIC к каким сигналам SSP идут? И в каком режиме работает TLV320AIC? DSP Mode? FS Pulse Mode (M1M0 = 00) /* TIMER2 for codec clock configuration -------------------------------------*/ SCU_APBPeriphClockConfig(__TIM23, ENABLE); /* Enable the clock for TIM2*/ TIM_DeInit(TIM2); TIM_DeInit(TIM3); /* GPIO6 configuration (PWM on P6.4) */ GPIO_Struct.GPIO_Pin = GPIO_Pin_4; GPIO_Struct.GPIO_Direction = GPIO_PinOutput; GPIO_Struct.GPIO_Type = GPIO_Type_PushPull; GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Disable; GPIO_Struct.GPIO_Alternate = GPIO_OutputAlt2; GPIO_Init(GPIO6,&GPIO_Struct); /* TIM02 Structure Initialization */ TIM_StructInit(&TIM_InitStruct); /* TIM2 Configuration in PWM Mode */ TIM_InitStruct.TIM_Mode = TIM_PWM; TIM_InitStruct.TIM_Clock_Source = TIM_CLK_APB; TIM_InitStruct.TIM_Prescaler = 0x00; TIM_InitStruct.TIM_Pulse_Level_1 = TIM_HIGH; TIM_InitStruct.TIM_Period_Level = TIM_LOW; TIM_InitStruct.TIM_Pulse_Length_1 = 10; TIM_InitStruct.TIM_Full_Period = 19; TIM_Init (TIM2, &TIM_InitStruct); /* SSP0 for codec configuration ----------------------------------------------*/ /* Enable the __SSP0 Clock */ SCU_APBPeriphClockConfig(__SSP0 ,ENABLE); SSP_DeInit(SSP0); /*Gonfigure SSP0_CLK, SSP0_MOSI, SSP0_nSS pins */ SCU_APBPeriphClockConfig(__GPIO5,ENABLE); GPIO_DeInit(GPIO5); GPIO_Struct.GPIO_Direction = GPIO_PinInput; GPIO_Struct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7; GPIO_Struct.GPIO_Type = GPIO_Type_PushPull ; GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Enable; GPIO_Struct.GPIO_Alternate = GPIO_InputAlt1 ; GPIO_Init (GPIO5, &GPIO_Struct); /*Gonfigure SSP0_MISO pin GPIO5.6*/ GPIO_Struct.GPIO_Direction = GPIO_PinOutput; GPIO_Struct.GPIO_Pin = GPIO_Pin_6; GPIO_Struct.GPIO_Type = GPIO_Type_PushPull ; GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Disable; GPIO_Struct.GPIO_Alternate = GPIO_OutputAlt2 ; GPIO_Init (GPIO5, &GPIO_Struct); /* SSP0 configuration */ SSP_DeInit(SSP0); SSP_InitStruct.SSP_FrameFormat = SSP_FrameFormat_TI ; SSP_InitStruct.SSP_Mode = SSP_Mode_Slave; SSP_InitStruct.SSP_CPOL = SSP_CPOL_Low; SSP_InitStruct.SSP_CPHA = SSP_CPHA_2Edge; SSP_InitStruct.SSP_DataSize = SSP_DataSize_16b; SSP_InitStruct.SSP_ClockRate = 2; SSP_InitStruct.SSP_ClockPrescaler = 12; SSP_InitStruct.SSP_SlaveOutput = SSP_SlaveOutput_Enable; SSP_Init(SSP0, &SSP_InitStruct); /* SSP0 enable */ SSP_Cmd(SSP0, ENABLE);
|
|
|
|
|
Jan 16 2008, 06:48
|
Участник

Группа: Свой
Сообщений: 51
Регистрация: 20-07-04
Пользователь №: 342

|
У меня микроконтроллер работал с датчиком, в силу особенностей которого чип-селект формировался программно. По поводу TLV320AIC ничего не могу сказать.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|