Forum: Mikrocontroller und Digitale Elektronik XMC4500 mit UART DMA


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Felix (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich benutze das XMC4500 Relax Kit inkl. XMC-Lib und versuche seit Tagen 
folgendes umzusetzen:
4 UART TX Outputs, welche mit Hilfe von DMA jeweils ein eigenes uint8_t 
Array parallel, also gleichzeitig senden.

Nach Vertiefen ins Datenblatt, sowie in die USIC und DMA Kapitel, kam 
ich zu folgendem Ansatz:

U0C0 für TX1 Output,
U0C1 für TX2 Output,
U1C0 für TX3 Output,
U1C1 für TX4 Output

Soweit so gut. Gleichzeitiges Sender der Arraybuffer unter Verwendung 
von nur TX1 und TX3 funktioniert wunderbar, ebenfalls von TX2 und TX4. 
Bei Verwendung von allen 4 TX, bzw. TX1 & TX2 oder TX3 & TX4, gibt es 
einen "Streit" zwischen den Channels des betreffenden USIC Moduls.

Meine Frage lautet nun: Kann das überhaupt so funktionieren wie ich es 
versuche, oder können beide Channels eines USIC Moduls nicht 
gleichzeitig?

Code reiche ich gerne bei Bedarf nach.

Vielen Dank,
Felix

von Felix (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Alle 4 Arrays sind mit gleichen Daten gefüllt. Mit einer durchgehenden 
Zahlenfolge von 0 bis 99.

Mein Code:
1
#define BUFFER_LENGTH 100
2
3
volatile uint8_t DMXBufferU0C0[BUFFER_LENGTH];
4
volatile uint8_t DMXBufferU0C1[BUFFER_LENGTH];
5
volatile uint8_t DMXBufferU1C0[BUFFER_LENGTH];
6
volatile uint8_t DMXBufferU1C1[BUFFER_LENGTH];
7
8
static XMC_UART_CH_CONFIG_t uart_config =
9
{
10
  .baudrate = 250000U,
11
  .oversampling = 16U,
12
  .data_bits = 8U,
13
  .frame_length = 8U,
14
  .stop_bits = 2U,
15
  .parity_mode = XMC_USIC_CH_PARITY_MODE_NONE
16
} ;
17
18
static XMC_DMA_CH_CONFIG_t U0C0_DMAChConfig =
19
{
20
  .dst_addr = (uint32_t)&(XMC_UART0_CH0->TBUF[0]),
21
  .src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
22
  .dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
23
  .src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
24
  .dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
25
  .src_burst_length = XMC_DMA_CH_BURST_LENGTH_8,
26
  .dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
27
  .transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
28
  .transfer_type = XMC_DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK,
29
  .dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
30
  .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR0_0,
31
  .enable_interrupt = true
32
};
33
34
static XMC_DMA_CH_CONFIG_t U0C1_DMAChConfig =
35
{
36
  .dst_addr = (uint32_t)&(XMC_UART0_CH1->TBUF[0]),
37
  .src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
38
  .dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
39
  .src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
40
  .dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
41
  .src_burst_length = XMC_DMA_CH_BURST_LENGTH_8,
42
  .dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
43
  .transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
44
  .transfer_type = XMC_DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK,
45
  .dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
46
  .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR0_1,
47
  .enable_interrupt = true
48
};
49
50
static XMC_DMA_CH_CONFIG_t U1C0_DMAChConfig =
51
{
52
  .dst_addr = (uint32_t)&(XMC_UART1_CH0->TBUF[0]),
53
  .src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
54
  .dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
55
  .src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
56
  .dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
57
  .src_burst_length = XMC_DMA_CH_BURST_LENGTH_8,
58
  .dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
59
  .transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
60
  .transfer_type = XMC_DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK,
61
  .dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
62
  .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR0_4,
63
  .enable_interrupt = true
64
};
65
66
static XMC_DMA_CH_CONFIG_t U1C1_DMAChConfig =
67
{
68
  .dst_addr = (uint32_t)&(XMC_UART1_CH1->TBUF[0]),
69
  .src_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
70
  .dst_transfer_width = XMC_DMA_CH_TRANSFER_WIDTH_8,
71
  .src_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_INCREMENT,
72
  .dst_address_count_mode = XMC_DMA_CH_ADDRESS_COUNT_MODE_NO_CHANGE,
73
  .src_burst_length = XMC_DMA_CH_BURST_LENGTH_8,
74
  .dst_burst_length = XMC_DMA_CH_BURST_LENGTH_1,
75
  .transfer_flow = XMC_DMA_CH_TRANSFER_FLOW_M2P_DMA,
76
  .transfer_type = XMC_DMA_CH_TRANSFER_TYPE_SINGLE_BLOCK,
77
  .dst_handshaking = XMC_DMA_CH_DST_HANDSHAKING_HARDWARE,
78
  .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR0_5,
79
  .enable_interrupt = true
80
};
81
82
void GPDMA0_0_IRQHandler(void)
83
{
84
  const uint8_t U0C0DMAChannel = 0;
85
  const uint8_t U0C1DMAChannel = 1;
86
  const uint8_t U1C0DMAChannel = 2;
87
  const uint8_t U1C1DMAChannel = 3;
88
89
  // Check DMA0.0 transfer complete
90
  if (XMC_DMA_CH_GetEventStatus(XMC_DMA0, U0C0DMAChannel) == XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE)
91
  {
92
    XMC_DMA_CH_ClearEventStatus(XMC_DMA0, U0C0DMAChannel, XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
93
    printf("U0C0 DMA Done!\n");
94
  }
95
96
  // Check DMA0.1 transfer complete
97
  if (XMC_DMA_CH_GetEventStatus(XMC_DMA0, U0C1DMAChannel) == XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE)
98
  {
99
    XMC_DMA_CH_ClearEventStatus(XMC_DMA0, U0C1DMAChannel, XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
100
    printf("U0C1 DMA Done!\n");
101
  }
102
103
  // Check DMA0.2 transfer complete
104
  if (XMC_DMA_CH_GetEventStatus(XMC_DMA0, U1C0DMAChannel) == XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE)
105
  {
106
    XMC_DMA_CH_ClearEventStatus(XMC_DMA0, U1C0DMAChannel, XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
107
    printf("U1C0 DMA Done!\n");
108
  }
109
110
  // Check DMA0.3 transfer complete
111
  if (XMC_DMA_CH_GetEventStatus(XMC_DMA0, U1C1DMAChannel) == XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE)
112
  {
113
    XMC_DMA_CH_ClearEventStatus(XMC_DMA0, U1C1DMAChannel, XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
114
    printf("U1C1 DMA Done!\n");
115
  }
116
}
117
118
void DMATEST(void)
119
{
120
  uint8_t n = 0;
121
122
  for (n = 0; n < BUFFER_LENGTH; n++)
123
  {
124
    DMXBufferU0C0[n] = n;
125
    DMXBufferU0C1[n] = n;
126
    DMXBufferU1C0[n] = n;
127
    DMXBufferU1C1[n] = n;
128
  }
129
130
  // Init General Purpose DMA 0
131
  XMC_DMA_Init(XMC_DMA0);
132
133
  //////////////////////////////////////////////////////////////////////
134
  initUARTDMA(DMXBufferU0C0, XMC_USIC0_CH0, 0, &U0C0_DMAChConfig, P1_5);
135
  initUARTDMA(DMXBufferU0C1, XMC_USIC0_CH1, 1, &U0C1_DMAChConfig, P2_5);
136
  initUARTDMA(DMXBufferU1C0, XMC_USIC1_CH0, 2, &U1C0_DMAChConfig, P0_5);
137
  initUARTDMA(DMXBufferU1C1, XMC_USIC1_CH1, 3, &U1C1_DMAChConfig, P0_1);
138
  //////////////////////////////////////////////////////////////////////
139
}
140
141
void initUARTDMA(uint8_t *Buffer, XMC_USIC_CH_t *USICChannel, uint8_t DMAChannel, XMC_DMA_CH_CONFIG_t *DMAChannelConfig, const XMC_GPIO_PORT_t *Port, const uint8_t Pin)
142
{
143
  // Init GPDMA0 using specified DMA config
144
  XMC_DMA_CH_Init(XMC_DMA0, DMAChannel, DMAChannelConfig);
145
146
  // Enable GPDMA channel event BLOCK_TRANSFER_COMPLETE
147
  XMC_DMA_CH_EnableEvent(XMC_DMA0, DMAChannel, XMC_DMA_CH_EVENT_BLOCK_TRANSFER_COMPLETE);
148
149
  // Route interrupt vector to the handler routine and enable DMA event handling
150
  BSP_IntVectSet(GPDMA0_0_IRQn, GPDMA0_0_IRQHandler);
151
  NVIC_SetPriority(GPDMA0_0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 63, 0));
152
  NVIC_EnableIRQ(GPDMA0_0_IRQn);
153
154
  // Init UART Channel
155
  XMC_UART_CH_Init(USICChannel, &uart_config);
156
157
  // Enable UART Event
158
  XMC_UART_CH_EnableEvent(USICChannel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
159
  XMC_USIC_CH_SetInterruptNodePointer(USICChannel, XMC_USIC_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER, 0);
160
161
  // Start UART Channel
162
  XMC_UART_CH_Start(USICChannel);
163
164
  // Make DMA ready
165
  XMC_USIC_CH_TriggerServiceRequest(USICChannel, 0);
166
167
  // Configure TX
168
  XMC_GPIO_SetMode(Port, Pin, XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT2);
169
  XMC_DMA_CH_SetBlockSize(XMC_DMA0, DMAChannel, BUFFER_LENGTH);
170
  XMC_DMA_CH_SetSourceAddress(XMC_DMA0, DMAChannel, (uint32_t)Buffer);
171
172
  // Enable DMA Channel
173
  XMC_DMA_CH_Enable(XMC_DMA0, DMAChannel);
174
}

von Felix (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die Lösung lag darin, dass in so einem Fall für die Channels 
unterschiedliche Service Request Numbers verwendet werden müssen:

Funktioniert falsch:
====================
1
U0C0 struct: .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR0_0
2
U0C1 struct: .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR0_1
3
U1C0 struct; .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR0_4
4
U1C0 struct; .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR0_5

Funktioniert richtig:
=====================
1
U0C0 struct: .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR0_0
2
U0C1 struct: .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC0_SR1_2
3
U1C0 struct; .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR0_1
4
U1C0 struct; .dst_peripheral_request = DMA0_PERIPHERAL_REQUEST_USIC1_SR1_3

Analog dazu müssen auch die XMC_USIC_CH_SetInterruptNodePointer() und 
XMC_USIC_CH_TriggerServiceRequest() entsprechend mit SR Number 0 oder 1 
aufgerufen werden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.