Forum: Mikrocontroller und Digitale Elektronik Daten via USART senden auf SAM V71


von TomMy (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite schon länger an einem Projekt, in dem ich Daten auf einem 
SAM V71 via eingerichteter USART-Schnittstelle übermitteln möchte. 
Leider schaffe ich es nicht eine entsprechende Funktion zu schreiben, 
die diese Aufgabe erfüllt.

Eine beispielhafte Struktur meiner Daten sieht wie folgt aus:
1
//example send_data(FUNCTIONCODE_Phasor, data, size);
2
#define FUNCTIONCODE_Phasor      0x1010
3
// data are results of a calculation
4
5
  int size = amount_of_channels_tft *(3)*sizeof(float) + config_bytes;
6
  char * data = (char *)malloc(size);
7
  char channels = (char)amount_of_channels_tft;
8
  char harmonics = (char)harmonic_number_tft;
9
  signed char *pt_amplitude;
10
  signed char *pt_phase;
11
  signed char *pt_frequency;
12
  signed char *pt_channels;
13
  signed char *pt_harmonics;
14
  pt_channels = (signed char*)&channels;
15
  memcpy(&data[0],pt_channels,1);
16
  pt_harmonics = (signed char*)&harmonics;
17
  memcpy(&data[1],pt_harmonics,1);
18
  for(int i = 0; i < amount_of_channels_tft; i++)
19
  {
20
    pt_amplitude = (signed char*)&fTFTAmplitude[1][i][finished_result_counter%5];
21
    memcpy(&data[(i*3)*sizeof(float) + config_bytes],pt_amplitude,4);
22
    pt_phase = (signed char*)&fTFTPhase[1][i][finished_result_counter%5];
23
    memcpy(&data[(i*(3) + 1)*sizeof(float) + config_bytes],pt_phase,4);
24
    pt_frequency = (signed char*)&fTFTFrequency[i][finished_result_counter%5];
25
    memcpy(&data[(i*(3) + 2)*sizeof(float) + config_bytes],pt_frequency,4);
26
  }
27
28
//send_data_function(FUNCTIONCODE_Phasor, data, size);

Da ich also ein Array mit einer gewissen Datengröße übertragen möchte, 
muss die Übertragung via USART im Zusammenhang mit dem XDMAC Modul 
geschehen oder könnte die Lösung auch anders aussehen? Ich sitze 
jedenfalls schon etwas länger an dem Problem, dass ich es nicht schaffe 
eine richtige Konfiguration für entsprechende USART-Übertragung mit 
XDMAC zu erstellen.

Ich würde mich freuen, wenn ihr mir helfen könnt oder jemand mögliche 
Erfahrungen mit mir teilt.

Gruß,
TomMy

von N2 (Gast)


Lesenswert?

Hi,

Niemand zwingt Dich zu DMA.

Wenn Du die Zeit hast, synchron zu übertragen, warum nicht?
ASynchron sollte aber gehen ausser Du macht sonst noch total
zeit abhängige Geschichten.

Ohne Code kann Dir da aber auch keiner bei DMA helfen...

Oder hast Du die Probleme, diese Struktur zu senden ?

Gruß N2

von TomMy (Gast)


Lesenswert?

Also ich empfange Daten von 9 ADCs durch eine SPI-Schnittstelle, die 
entsprechend verarbeitet, fouriertransformiert etc. werden und in der 
oben dargestellten Struktur hinterlegt werden. Hatte ein ähnliches 
Projekt schon mal lauffähig auf einem SAM4(mit DMAC- und PMC-Modul), 
aber bei dem V71 habe ich einfach Probleme in Verbindung mit dem XDMAC 
überhaupt was zu senden. Die Doku beim neuen Board empfinde ich da 
einfach lange nicht so hilfreich und enthält auch nicht gerade viel 
Beispielcode.


Als eine Möglichkeit zur Initialisierung eines entsprechenden Kanals 
habe ich z.B.den folgenden Code:
1
/* Initialize and enable DMA controller */
2
  pmc_enable_periph_clk(ID_XDMAC);
3
4
  /*Enable XDMA interrupt */
5
  NVIC_ClearPendingIRQ(XDMAC_IRQn);
6
  NVIC_SetPriority( XDMAC_IRQn ,1);
7
  NVIC_EnableIRQ(XDMAC_IRQn);
8
  
9
  xdmac_channel_cfg.mbr_ubc = MICROBLOCK_LEN;
10
  xdmac_channel_cfg.mbr_sa = &Decoded_Byte_Array[0];
11
  xdmac_channel_cfg.mbr_da = (uint32_t)&USART0->US_THR;     //Usart
12
  xdmac_channel_cfg.mbr_cfg = XDMAC_CC_SWREQ_HWR_CONNECTED |
13
    XDMAC_CC_MEMSET_NORMAL_MODE |
14
    XDMAC_CC_MBSIZE_SINGLE |
15
    XDMAC_CC_DWIDTH_BYTE |
16
    XDMAC_CC_SIF_AHB_IF0 |
17
    XDMAC_CC_DIF_AHB_IF0 |
18
    XDMAC_CC_SAM_FIXED_AM;
19
  xdmac_channel_cfg.mbr_bc = BLOCK_LEN - 1;
20
  xdmac_channel_cfg.mbr_ds =  0;
21
  xdmac_channel_cfg.mbr_sus = 0;
22
  xdmac_channel_cfg.mbr_dus = 0;
23
24
  xdmac_configure_transfer(XDMAC, USART0_DMAC_ID_TX, &xdmac_channel_cfg);
25
  xdmac_channel_enable(XDMAC, USART0_DMAC_ID_TX);

Aber ich komm echt nicht drauf, wie ich das zum erfolgreichen Senden mit 
meiner Struktur verknüpfen könnte.

von Adam P. (adamap)


Lesenswert?

TomMy schrieb:
> Aber ich komm echt nicht drauf, wie ich das zum erfolgreichen Senden mit
> meiner Struktur verknüpfen könnte.

Also versteh ich dich richtig, dass dieser Code funktioniert - um dein 
'Decoded_Byte_Array' zu versenden?

Falls ja, warum legst du dann den 'mbr_sa' nicht auf die Adresse deiner 
Struktur?

von TomMy (Gast)


Lesenswert?

Genauso bin ich auch vorgegangen. Damit ihr es einmal viel besser 
nachvollziehen könnt, seht ihr unten mal mein Programm auf das nötigste 
reduziert mit einem Testarray "src_buf". Selbst bei dieser einfachen 
Struktur erzeuge ich keine Ausgabe von Daten über die 
USART-Schnittstelle. Ich bin mir auch ziemlich sicher, dass in 
"conf_clock" und "conf_uart_serial" die  richtigen Konfigurationen für 
USART und Clock hinterlegt sind, sodass ich vermute, dass meine Main 
noch einen groben Fehler enthält.


Vielen Dank schon mal für die jetzigen Antworten und mögliche weitere, 
die folgen!

Gruß,
TomMy
1
#include <asf.h>
2
#include <conf_board.h>
3
#include <conf_clock.h>
4
#include <conf_uart_serial.h>
5
6
/** XDMA channel used in this example. */
7
#define XDMA_CH 0
8
/** The buffer size for transfer  */
9
#define BUFFER_SIZE               512
10
11
static xdmac_channel_config_t xdmac_channel_cfg; //
12
#define MICROBLOCK_LEN       16 
13
#define BLOCK_LEN            16
14
#define USART1_DMAC_ID_TX    7
15
16
uint32_t i;
17
18
COMPILER_ALIGNED(8)
19
static uint8_t src_buf[BUFFER_SIZE];
20
21
static void configure_console(void)
22
{
23
  const usart_serial_options_t uart_serial_options = {
24
    .baudrate = CONF_UART_BAUDRATE,
25
    .charlength = CONF_UART_CHAR_LENGTH,
26
    .paritytype = CONF_UART_PARITY,
27
    .stopbits = CONF_UART_STOP_BITS,
28
  };
29
30
  /* Configure console UART. */
31
  sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
32
  stdio_serial_init(CONF_UART, &uart_serial_options);
33
}
34
35
36
37
38
39
int main (void)
40
{  
41
  uint32_t i;  
42
  
43
  /* Insert system clock initialization code here (sysclk_init()). */
44
45
46
  /* Initialize the system */
47
  sysclk_init();
48
  board_init();
49
50
  /* Configure console UART */
51
  configure_console();
52
  
53
  /* Initialize source and destination buffer */
54
  for (i = 0; i < BUFFER_SIZE; i++) {
55
    src_buf[i] = 0x55;
56
  }
57
58
  
59
  //***************** DMA SETUP ********************
60
    /* Initialize and enable DMA controller */
61
    pmc_enable_periph_clk(ID_XDMAC);
62
    /*Enable XDMA interrupt */
63
    NVIC_ClearPendingIRQ(XDMAC_IRQn);
64
    NVIC_SetPriority( XDMAC_IRQn ,1);
65
    NVIC_EnableIRQ(XDMAC_IRQn);
66
    
67
    xdmac_channel_cfg.mbr_ubc = MICROBLOCK_LEN;
68
    xdmac_channel_cfg.mbr_sa = (uint32_t)&src_buf;
69
    xdmac_channel_cfg.mbr_da = (uint32_t)&USART1->US_THR;
70
    xdmac_channel_cfg.mbr_cfg =   XDMAC_CC_TYPE_PER_TRAN | 
71
        XDMAC_CC_MBSIZE_SINGLE | 
72
        XDMAC_CC_DWIDTH_BYTE |
73
        XDMAC_CC_DSYNC_MEM2PER | 
74
        XDMAC_CC_SWREQ_HWR_CONNECTED |
75
        XDMAC_CC_MEMSET_NORMAL_MODE | 
76
        XDMAC_CC_SIF_AHB_IF1 | 
77
        XDMAC_CC_DIF_AHB_IF1 | 
78
        XDMAC_CC_SAM_INCREMENTED_AM |
79
        XDMAC_CC_DAM_FIXED_AM |
80
        XDMAC_CC_PERID(USART1_DMAC_ID_TX);
81
    xdmac_channel_cfg.mbr_bc = BLOCK_LEN - 1;
82
    xdmac_channel_cfg.mbr_ds =  0;
83
    xdmac_channel_cfg.mbr_sus = 0;
84
    xdmac_channel_cfg.mbr_dus = 0;
85
    xdmac_configure_transfer(XDMAC, XDMA_CH, &xdmac_channel_cfg);
86
    
87
    xdmac_enable_interrupt(XDMAC, XDMA_CH);
88
    xdmac_channel_enable_interrupt(XDMAC, XDMA_CH, XDMAC_CIE_BIE);
89
    xdmac_channel_enable(XDMAC, XDMA_CH);
90
  
91
  void XDMAC_Handler(void)
92
  {
93
    uint32_t dma_status;
94
    dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_CH);
95
    xdmac_channel_cfg.mbr_sa = (uint32_t)&src_buf;
96
    xdmac_configure_transfer(XDMAC, XDMA_CH, &xdmac_channel_cfg);
97
    
98
  };
99
100
}

von Adam P. (adamap)


Lesenswert?

Was macht die 'void XDMAC_Handler(void)' innerhalb der main? Oder hast 
du hier nur die Klammern falsch gesetzt?

von Adam P. (adamap)


Lesenswert?

1
#define USART1_DMAC_ID_TX    7

USART1 ist aber 9 - 7 ist USART0!
...nicht das du nun am falschen Port auf Daten wartest.

von TomMy (Gast)


Lesenswert?

Sorry, ich hab beim Kopieren nur die Klammern falsch gesetzt. Der 
XDMAC_Handler ist in meinem Code normalerweise außerhalb der main.

von TomMy (Gast)


Lesenswert?

Vielen Dank schon mal, Adam! Tatächlich hatte ich das falsch gesetzt und 
am falschen Port gewartet.
Scheint aber leider nicht der einzige Fehler gewesen zu sein, da eine 
Ausgabe immer noch nicht vorhanden ist :(

von Adam P. (adamap)


Lesenswert?

TomMy schrieb:
> xdmac_channel_cfg.mbr_sa = (uint32_t)&src_buf;

Versuch mal das & wegzulassen.
1
xdmac_channel_cfg.mbr_sa = (uint32_t)src_buf;

Sonst sieht der Init. ok aus :-/

von TomMy (Gast)


Lesenswert?

Habe ich mal direkt ausprobiert, ist aber scheinbar nicht die 
vollständige Lösung des Problems :(

von Adam P. (adamap)


Lesenswert?

Kannst da mal schauen...

https://github.com/avrxml/asf/blob/master/sam/drivers/spi/spi_xdmac_example/spi_xdmac_example.c

Da überträgt er via SPI, sollte vom Aufbau das gleiche sein -
jedoch siehts deinem sehr ähnlich.

edit:
Leider hab ich kein SAM V Board, sonst würd ich es gleich mal selbst 
versuchen ;-)

Beim V71 gibts halt kein Bsp. mit USART und XDMAC, hab ich auch geschaut 
- aber schau mal bei anderen µC die XDMAC haben, ob da was hinterlegt 
ist und der Aufbau gleich ist, vllt. XMEGA Reihe oder andere Cortex µC 
mit XDMAC.

Bei dem SAM4E hab ich auch nach etwas gesucht, gabs net, aber Infos beim 
anderen µC Typ gefunden (Application Notes / Example Projects).

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Muss man doch nur in die Referenz schauen ;) . Also im Normalfall war es 
immer so wenn man die Peripherie(Usart) aktiviert das dann der Transfer 
startet.

Versuche doch erst mal so etwas auf die Usart auszugeben. Wenn das 
klappt dann fehlt der trigger und der ist eigentlich wie gesagt das man 
die Komponente aktiviert. Diese triggert sich dann selber durch das 
entsprechende BIT in der Usart wenn der Buffer leer ist. Der DMA 
Controller schiebt dann Daten nach...

von Adam P. (adamap)


Lesenswert?

Hey...bist du weiter gekommen?

von TomMy (Gast)


Lesenswert?

Hey Adam, vielen Dank für dein Interesse und Nachfragen! Leider konnte 
ich das Problem bis heute nicht lösen :(

von Adam P. (adamap)


Lesenswert?

Welchen SAM V71 hast du?
Hast du das SAM V71 Xplained Board oder ein eigen Entwickeltes?

von TomMy (Gast)


Lesenswert?

Ja genau, habe das V71 Xplained Ultra Board!

von Adam P. (adamap)


Lesenswert?

Welche UART nutzt du als CONF_UART für deine Debug-Ausgaben,
hoffe diese und die für XDMAC sind nicht die gleichen?

Hast du mal versucht, auf der gewünschten UART erstmal etwas ganz 
"normal" zu versenden? mittels uart_write / uart_put - wie die Fkt. auch 
heißen.

: Bearbeitet durch User
von TomMy (Gast)


Lesenswert?

Ich nutze USART1 als CONF_UART. Ich bin anfangs mit einem kleinem 
Programm mit der selben Konfiguration und einer putchar-Fkt gestartet, 
das zu Testzwecken zunächst einfache Characters überträgt. Das hat auch 
alles soweit geklappt ;)

von Adam P. (adamap)


Lesenswert?

Also möchtest du dein "Console-Port" (USART1) mit DMA nutzen?
Weil:

TomMy schrieb:
> Ich nutze USART1 als CONF_UART

Das bedeutet: USART1 = CONF_UART = USART1_DMAC_ID_TX

von Adam P. (adamap)


Lesenswert?

Hey TomMy,

hab da was für dich :-)

Bei Atmel-Start
http://start.atmel.com/#examples/SAMV71XplainedUltra

"Search: DMA"

gibt es ein Beispiel mit USART und DMA.

Könntest ja da mal schauen, ob du was findest und es mit deinem Source 
vergleichen (auch wenn da der Source Aufbau anders ist) -> ASF4.

von TomMy (Gast)


Lesenswert?

Hey Adam! Ich schaue es mir morgen mal genauer an. Falls ich die Lösung 
meines Problems finde, werde ich euch teilhaben lassen ;-)

Vielen Dank!

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.