Atmel SAMD21 DMA Transfer Interrupt completo non attivato


0

Ho configurato le periferiche SAMD21 in modo che i dati audio in ingresso da I2S vengano copiati in un buffer di memoria con DMA. Poiché il controller consente descrittori DMA collegati, ho due descrittori collegati back-to-back, ciascuno che scrive su un buffer diverso.

inserisci qui la descrizione dell'immagine

Quando un trasferimento a blocchi è giunto al termine, BTCNT ha raggiunto lo zero, il bit valido nel registro di controllo del trasferimento a blocchi verrà scritto a zero nel descrittore di trasferimento interno per il canale attivo prima che l'intero descrittore di trasferimento venga scritto nel write-back memoria. Gli interrupt opzionali, Trasferimento canale completo e Sospensione canale e l'evento di uscita opzionale, Blocco, verranno generati se configurati e abilitati. Se è stato l'ultimo trasferimento a blocchi in una transazione, il registro Indirizzo successivo (DESCADDR) conterrà il valore 0x00000000 e il canale DMA verrà sospeso o disabilitato, a seconda della configurazione nel gruppo di bit Azione blocco nel registro Controllo trasferimento blocchi (BTCTRL.BLOCKACT)

Questo estratto dal foglio dati accoppiato all'immagine suggerisce che l'interruzione verrà attivata dopo ogni trasferimento di blocco, implicando che l'ISR viene eseguito ogni volta che viene caricato il successivo descrittore collegato. Ma nella mia configurazione, l'ISR non viene eseguito affatto. Dopo aver configurato la catena collegata per avere una terminazione, l'ISR si è attivato dopo il trasferimento a blocchi della catena. Sembra che l'interruzione si attivi solo dopo una completa transazione , non dopo ogni trasferimento di blocchi come suggerisce il foglio dati.

Sto interpretando il foglio dati in modo errato, c'è un modo per far eseguire la routine ISR su ciascun collegamento?

static void _config_dma_for_rx(void)
{   
    struct dma_resource_config config;
    dma_get_config_defaults(&config);

    config.trigger_action = DMA_TRIGGER_ACTION_BEAT;
    config.peripheral_trigger = CONF_RX_TRIGGER;


    dma_allocate(&rx_dma_resource, &config);



    // Configure DMA RX Descriptor A
    struct dma_descriptor_config descriptor_config;

    dma_descriptor_get_config_defaults(&descriptor_config);

    descriptor_config.block_transfer_count = 32;
    descriptor_config.beat_size = DMA_BEAT_SIZE_HWORD;
    descriptor_config.step_selection = DMA_STEPSEL_SRC;
    descriptor_config.src_increment_enable = false;
    descriptor_config.destination_address = (uint32_t)rx_values_a+ sizeof(rx_values_a);
    descriptor_config.source_address = (uint32_t)&CONF_I2S_MODULE->DATA[1];

    dma_descriptor_create(&rx_dma_descriptor_a, &descriptor_config);

    rx_dma_descriptor_a.DESCADDR.reg = 0;// (uint32_t)&rx_dma_descriptor_b;


    // Configure DMA RX Descriptor B

    dma_descriptor_get_config_defaults(&descriptor_config);

    descriptor_config.block_transfer_count = 32;
    descriptor_config.beat_size = DMA_BEAT_SIZE_HWORD;
    descriptor_config.step_selection = DMA_STEPSEL_SRC;
    descriptor_config.src_increment_enable = false;
    descriptor_config.destination_address = (uint32_t)rx_values_b +  sizeof(rx_values_b);
    descriptor_config.source_address = (uint32_t)&CONF_I2S_MODULE->DATA[1];

    dma_descriptor_create(&rx_dma_descriptor_b, &descriptor_config);

    rx_dma_descriptor_b.DESCADDR.reg = (uint32_t)&rx_dma_descriptor_a;




    dma_add_descriptor(&rx_dma_resource, &rx_dma_descriptor_a);


    dma_register_callback(&rx_dma_resource, rx_done_callback, DMA_CALLBACK_TRANSFER_DONE);
    dma_enable_callback(&rx_dma_resource, DMA_CALLBACK_TRANSFER_DONE);


    dma_start_transfer_job(&rx_dma_resource);
}

Risposte:


0

Il registro di controllo del trasferimento a blocchi ha un campo BLOCKACT che indica l'azione da eseguire dopo ciascun blocco. Dopo averlo configurato su INT (canale in funzionamento normale e interruzione di blocco), il DMA ha continuato a funzionare continuamente, attivando l'ISR alla fine di ogni trasferimento di blocco. Ho dovuto aggiungere la seguente riga alla configurazione di ciascuno dei due descrittori.

descriptor_config.block_action = DMA_BLOCK_ACTION_INT;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.