Forum: Mikrocontroller und Digitale Elektronik [AVR xmega A] Senden von DMA -> USART, funktioniert nur teilweise


von Mats S. (matsstriker)


Lesenswert?

Hallo!

erst einmal die gute Nachricht.. das Senden von einem Byte/Zeichen von 
DMA zu USART funktioniert.

Die Schlechte ist, dass es bei einem Feld von 1000 Zeichen nur einzelne 
Zeichen des Arrays gesendet werden. Im Array sind ASCII-Zeichen zwischen 
Zeichen 33 bis 126.

Die Ausgabe auf dem Terminal der Seriellen Schnittstelle ist:
1
Hello AVR world ! :!"#=Zv5Rn-If$A^z9Ur0Mj(Ea~<Yv4Qm,He$@ld ! :!


Der dazugehörige Sourcecode (basieren auf dem Atmel ASF Example von 
AVRxmegaA1 Xplained: DMA_EXAMPLE21):
1
int main(void)
2
{
3
    struct dma_channel_config config;
4
  
5
    pmic_init();
6
    board_init();
7
    sysclk_init();
8
    sleepmgr_init();
9
  
10
    // USART options.
11
    static usart_rs232_options_t USART_SERIAL_OPTIONS = {
12
        .baudrate = USART_SERIAL_EXAMPLE_BAUDRATE,
13
        .charlength = USART_SERIAL_CHAR_LENGTH,
14
        .paritytype = USART_SERIAL_PARITY,
15
        .stopbits = USART_SERIAL_STOP_BIT
16
    };
17
  
18
    // Initialize usart driver in RS232 mode
19
    usart_init_rs232(USART_SERIAL_EXAMPLE, &USART_SERIAL_OPTIONS);
20
      
21
    uint8_t tx_buf[] = "\nHello AVR world ! :";
22
    uint8_t tx_length = 20;
23
    uint8_t i = 0;
24
    for (i = 0; i < tx_length; i++) {
25
        usart_putchar(USART_SERIAL_EXAMPLE, tx_buf[i]);
26
    }
27
      
28
    dma_enable();
29
  
30
    dma_set_callback(DMA_CHANNEL, example_dma_transfer_done);
31
  
32
    /* Make sure config is all zeroed out so we don't get any stray bits */
33
    memset(&config, 0, sizeof(config));
34
  
35
    /*
36
     * This example will configure a DMA channel with the following
37
     * settings:
38
     *  - CHANGED: High interrupt priority
39
     *  - 1 byte burst length
40
     *  - DMA_BUFFER_SIZE bytes for each transfer
41
     *  - CHANGED: Reload source only (not destination) address at end of each transfer
42
     *  - CHANGED: Increment only source (not destination) address during transfer
43
     *  - Source address is set to \ref source
44
     *  - Destination address is set to \ref destination
45
     */
46
    dma_channel_set_interrupt_level(&config, DMA_INT_LVL_HI);
47
    dma_channel_set_burst_length(&config, DMA_CH_BURSTLEN_1BYTE_gc);
48
    dma_channel_set_transfer_count(&config, DMA_BUFFER_SIZE);
49
    //dma_channel_set_single_shot(&config);
50
      
51
    dma_channel_set_src_reload_mode(&config,DMA_CH_SRCRELOAD_TRANSACTION_gc);
52
    dma_channel_set_dest_reload_mode(&config,DMA_CH_DESTRELOAD_NONE_gc);    
53
    dma_channel_set_src_dir_mode(&config, DMA_CH_SRCDIR_INC_gc);
54
    dma_channel_set_dest_dir_mode(&config, DMA_CH_DESTDIR_FIXED_gc);
55
    dma_channel_set_source_address(&config, (uint16_t)(uintptr_t)source);
56
    //dma_channel_set_destination_address(&config, (uint16_t)(uintptr_t)destination);
57
    uint16_t uartc0_data_addr = 0x08A0;     //USARTC0_DATA
58
    dma_channel_set_destination_address(&config, uartc0_data_addr);
59
    dma_channel_set_trigger_source(&config, DMA_CH_TRIGSRC_USARTC0_DRE_gc);
60
    //USARTC0.CTRLA |= USART_DREINTLVL0_bm;
61
      
62
    dma_channel_write_config(DMA_CHANNEL, &config);
63
  
64
    /* Use the configuration above by enabling the DMA channel in use. */
65
    dma_channel_enable(DMA_CHANNEL);
66
      
67
    cpu_irq_enable();
68
    
69
    while (true) {
70
    }
71
}

habt ihr eine Idee wieso statt 1000 ASCII-Zeichen nur ein Teil davon 
gesendet wird??

: Bearbeitet durch User
von tester (Gast)


Lesenswert?

erster gedanke: stimmen die eingestellten baudraten etc. ?

von Mats S. (matsstriker)


Lesenswert?

tester schrieb:
> erster gedanke: stimmen die eingestellten baudraten etc. ?
denke schon.. sonst würden garkeine Zeichen ankommen..

Die Ausgabe auf dem Terminal der Seriellen Schnittstelle ist:
1
Hello AVR world ! :!"#=Zv5Rn-If$A^z9Ur0Mj(Ea~<Yv4Qm,He$@ld ! :!


Ich betreibe den AVRxmega mit 16MHz und verwende für den UART eine 
Baudrate von 1.000.000Bit/s (soll absichtlich am Maximum mit dieser 
Frequenz betrieben werden).
Das normale Senden über den UART funktioniert auch mit diesen 
Einstllungen.

von Daniel V. (danvet)


Lesenswert?

Wie stellt der DMA-Kanal sicher, dass er erst in die UART schreibt, wenn 
diese ihr letztes Zeichen gesendet hat? Ansonsten wird das Senden immer 
wieder überschrieben/unterbrochen.

von Mats S. (matsstriker)


Lesenswert?

Daniel V. schrieb:
> Wie stellt der DMA-Kanal sicher, dass er erst in die UART schreibt, wenn
> diese ihr letztes Zeichen gesendet hat? Ansonsten wird das Senden immer
> wieder überschrieben/unterbrochen.
mit der Zeile:
dma_channel_set_trigger_source(&config, DMA_CH_TRIGSRC_USARTC0_DRE_gc);


Diese war versehentlich auskommentiert.
Getestet habe ich das Programm aber mit diesem Trigger.

von Daniel V. (danvet)


Lesenswert?


von Mats S. (matsstriker)


Lesenswert?

Okay,

ich hab die Lösung gefunden :)

und zwar musste ich Single-Shot Transfer aktivieren und Source-, sowie 
Destination nicht "reloaden".

folgende Config. funktioniert nun bei mir:
1
    dma_channel_set_interrupt_level(&config, DMA_INT_LVL_HI);
2
    dma_channel_set_burst_length(&config, DMA_CH_BURSTLEN_1BYTE_gc);
3
    dma_channel_set_transfer_count(&config, DMA_BUFFER_SIZE);
4
    dma_channel_set_single_shot(&config);
5
    dma_channel_set_src_reload_mode(&config,DMA_CH_SRCRELOAD_NONE_gc);
6
    dma_channel_set_dest_reload_mode(&config,DMA_CH_DESTRELOAD_NONE_gc);    
7
    dma_channel_set_src_dir_mode(&config, DMA_CH_SRCDIR_INC_gc);
8
    dma_channel_set_dest_dir_mode(&config, DMA_CH_DESTDIR_FIXED_gc);
9
    dma_channel_set_source_address(&config, (uint16_t)(uintptr_t)source);
10
    uint16_t uartc0_data_addr = 0x08A0;     //USARTC0_DATA
11
    dma_channel_set_destination_address(&config, uartc0_data_addr);
12
    dma_channel_set_trigger_source(&config, DMA_CH_TRIGSRC_USARTC0_DRE_gc);

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.