Re: Ukončení přenosu využitím DMA
Tomáš Hamouz
hamouz na divesoft.cz
Středa Září 14 12:47:05 CEST 2016
> No toto mi vobec nedava zmysel. Takze nakoniec sa aj pri tom "zakopnuti"
> prenesie ocakavany pocet znakov (/ 8 = pocet clockov zodpovedajuci poctu
> bytov nastavenych v Tx DMA), ale v Rx buffri nie su?
Pokud dojde k zakopnutí, tak se přenos ukončí předčasně. Z nějakého
důvodu vypadne ze smyčky kde se čeká až Rx kanál DMA skončí přenos.
> while(SET == DMA_GetChannelActiveStatus(SSP1_DMA_CHAN_RX)) {;}
(Ta funkce jen testuje příslušný bit, nic jiného)
Kanál se dle DS zastaví buď přenesením daného počtu přenosů, nebo
výskytem chyby, nebo ručně.
Standardně po ukončení přenosu v následujícím kódu oba kanály (pro
sichr) zastavím ručně. Za normálních okolností jsou už oba stopnuté.
> DMA_ChannelCmd(SSP1_DMA_CHAN_RX, DISABLE);
> DMA_ChannelCmd(SSP1_DMA_CHAN_TX, DISABLE);
Protože mi vypadne z výše uvedené smyčky dříve, utnu tím i Tx kanál.
Tím se vysvětluje proč se přestane odesílat FF, ale záhadou je proč
dojde k předčasnému stopnutí Rx kanálu. Přitom Tx kanál se
pravděpodbně nezastaví, tak až pak zastavím v kódu.
> Chcelo by to pozriet ako je to prelozene.
Ta čekací smyčka, o kterou předpokládám jde
Debug build
while(SET == DMA_GetChannelActiveStatus(SSP1_DMA_CHAN_RX)) {;}
0000EC68 E1A00000 mov r0, r0
0000EC6C E59F3130 ldr r3, 0x0000EDA4
0000EC70 E5933000 ldr r3, [r3]
0000EC74 E1A00003 mov r0, r3
0000EC78 E59F3130 ldr r3, 0x0000EDB0
0000EC7C E12FFF33 blx r3
0000EC80 E1A03000 mov r3, r0
0000EC84 E3530001 cmp r3, #1
0000EC88 0AFFFFF7 beq 0x0000EC6C
0000EDA4 040006DC .word 0x040006DC ; *DMA_Channel5
0000EDB0 0000C498 .word 0x0000C498 ; DMA_GetChannelActiveStatus
Release build
0000A320 E59F4088 ldr r4, 0x0000A3B0
while(SET == DMA_GetChannelActiveStatus(SSP1_DMA_CHAN_TX)) {;}
0000A324 E59F0080 ldr r0, 0x0000A3AC
0000A328 E12FFF34 blx r4
0000A32C E3500001 cmp r0, #1
0000A330 0AFFFFFB beq 0x0000A324
0000A3AC 780001A0 .word 0x780001A0 ; DMA_Channel5
0000A3B0 00007C18 .word 0x00007C18 ; DMA_GetChannelActiveStatus
> Bolo by tiez dobre mat pred,
> medzi a za tymi while nejaku znacku (zacvicit nejakym pinom) a pozerat
> osciloskopom/LA spolu s tymi hodinami od SPI.
Přesně tak jsem to dělal.
Tomáš
> wek
> ----- Original Message ---------------
>>Není. Přiąel jsem na to tak ľe mi neseděly kontrolní součty v datech
>>a v bufferu zůstaly nuly.
>>
>>Kdyľ koukám na SPI signály log. analyzátorem, tak v případě zkrácení
>>je několik znaků před předčasným koncem zaąkytnutí, je tam mezera cca na jeden
>>znak (SPI na 24MHz). Potom doběhne jeątě pár znaků, zachytil jsem v
>>rozsahu 4-13. Celkový počet i počet po mezeře jsou nekulatá čísla.
>>
>>Zřejmě dochází skutečně k zastavení kanálu, ale chyba nastavená není.
>>
>>A to vąe jen občas. Přeruąení je povolené, po 1ms běľí systémové
>>hodiny, ale na SPI se nesahá.
>>
>>Tomáą
>>
>>
>>> A nie je to nahodou naopak, t.j. ze ak kontrolujete Rx tak je to dobre, a
>>> ak Tx tak Vam chybaju nejake prenesene data?
>>
>>> wek
>>
>>
>>> ----- Original Message ---------------
>>>>Zdravím vespolek
>>>>
>>>>Narazil jsem na problém, zdá se µe i opravil, ale netu±ím proč ta
>>>>oprava funguje.
>>>>
>>>>Procesor STR912FAW46 (vím, moc lidí s ním uµ nepracuje, ale co kdyby)
>>>>Přená±ím data přes SPI (externí flash) s vyuµitím DMA.
>>>>Programově ode±lu záhlaví, pro přenos dat pouµiju DMA. Tzn. odesílám
>>>>samá FF pomocí jednoho DMA kanálu, přijímám do bufferu pomocí druhého
>>>>kanálu. To v±e synchronně, čekám na dokončení přenosu.
>>>>
>>>>Vypadá to zhruba takhle:
>>>>
>>>> // tady je inicializace kanálů, oba na stejnou délku dat.
>>>>
>>>> // rict SSP ze bude prenaset prijata data pomoci DMA / dtto pro odesilana
>>>> SSP_DMACmd(SSP1, SSP_DMA_Receive, ENABLE);
>>>> SSP_DMACmd(SSP1, SSP_DMA_Transmit, ENABLE);
>>>>
>>>> // Enable DMA Channels
>>>> DMA_ChannelCmd(SSP1_DMA_CHAN_RX, ENABLE);
>>>> DMA_ChannelCmd(SSP1_DMA_CHAN_TX, ENABLE);
>>>>
>>>> // zde probiha prenos
>>>>
>>>> // pockat na dokonceni DMA prenosu
>>>> // vvvvvv zde je to dulezite
>>>> while(SET == DMA_GetChannelActiveStatus(SSP1_DMA_CHAN_RX)) {;}
>>>> // pockat az dobehne i SPI
>>>> while((SSP1->SR & SPI_SR_FLAG_BUSY)) {;}
>>>>
>>>> // Disable DMA Channels
>>>> DMA_ChannelCmd(SSP1_DMA_CHAN_RX, DISABLE);
>>>> DMA_ChannelCmd(SSP1_DMA_CHAN_TX, DISABLE);
>>>>
>>>> // Disable SPI RX/TX request
>>>> SSP_DMACmd(SSP1, SSP_DMA_Transmit, DISABLE);
>>>> SSP_DMACmd(SSP1, SSP_DMA_Receive, DISABLE);
>>>>
>>>>A teď ten problém: vět±inou to funguje, jen občas se přenos nedokončí,
>>>>přesněji, ukončí předčasně. Nehlásíá se µádné chyb, jen se přenese
>>>>míň neµ jsme zadával.
>>>>
>>>>Pokud na označené řádce kontroluju status Tx, tak to funguje.
>>>>
>>>>Délka dat pro oba kanály je inicializovaná ze stejné proměnné.
>>>>Proč záleµí na tom který kanál testuju, kdyµ by oba měly z principu
>>>>přenést stejné mnoµství dat?
>>>>
>>>>Tomá±
>>>>
Další informace o konferenci Hw-list