XMC4500 mit UART DMA

Gast #5495787
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
Angehängte Dateien:
Gast #5495825
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
}
Gast #5496135
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.
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren