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