Forum: Mikrocontroller und Digitale Elektronik XMC4500 mit UART DMA


von Felix (Gast)


Angehängte Dateien:

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)


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:

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.

von amelia (Gast)


Lesenswert?

Hey,
I am working with a dog motor.
I wanted to send a 8bytes data via uart.
could you help me with it ?

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.