AnsweredAssumed Answered

STM32F030 multiple UART problems

Question asked by jongerius.elmar on Jun 11, 2016
Latest reply on Jun 12, 2016 by jongerius.elmar
Hi there,

I am building together a system which should use multiple USARTS on a STM32F030C8T6 micro. One USART (USART1) will be used as a diagnostics port, whereas the other USART (USART2) will be switching back an forth between RS485 and RS232 operation.

USART1 will be running on 115k2 baud, connected to GPIOA9 (Tx) and GPIOA10 (Rx).
USART2 will be running on 9600 baud, connected to GPIOA2 (Tx) and GPIOA3 (Rx), and GPIOA1 for DataEnable in RS485 mode.

When I test everything separately my code works perfectly. If I combine code to run at the same time (multiple coöperative statemachines) there is a problem with USART1 stopping to work properly. Both USARTs don`t have too much to do, so reception is interrupt based and transmitting is polling.

Symptoms:
- USART1 Tx pin drive is very weak. If I add a certain pullup on this Tx pin I can recognize data again. I am sure that the receiving side (FTDI cable, tried also to connect via 100r resistors) is correct as there is no voltage across these resistors, and even disconnecting this cable from my MCU will keep the same symptoms. It looks like the Tx pin is driven as a opendrain type of output to me.
- Reception of USART1 is still perfect.
- Tx interrupts are normally generated and data is flowing out of the MCU, only the pin has an awfully high risetime. (falltime is OK).

Workarounds:
- These symptoms do not occur when I am not using the USART2. (excluding the complete USART2 code make USART1 fully functional).
- I was able to workaround this to first initialize USART1, wait a few seconds and then initialize USART2. This kind off works until I use my project via a bootloader, which requires USART1 for loading.

I can see some comments coming up "check your code": I tried to do that as far as I could go. I checked that the peripheral addresses where OK in my include files, there are no references to USART1 in my USART2 functions etc.

Could you help me look at my code, and try to give me some advise?

Toolchain:
CooCox: 1.7.7
GCC: 4.9 2014q4
MCU: STM32F030C8T6
Programmer: STlinkV2

Code for USART1:
01.void USART1_Init(void) {
02.    GPIO_InitTypeDef GPIO_InitStruct;
03.    NVIC_InitTypeDef NVIC_InitStructure;
04.    USART_InitTypeDef USART_InitStructure;
05. 
06.    USART_DeInit(USART1);
07. 
08.    /* Enable GPIO clock */
09.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
10. 
11.    /* Enable USARTx clock */
12.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
13. 
14.    /* Connect PXx to USARTx_Tx */
15.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
16.    /* Connect PXx to USARTx_Rx */
17.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
18. 
19.    /*Configure GPIO pin: PA9 (USART1 TX)*/
20.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
21.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
22.    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;         //Test?
23.//  //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;         //Test?
24.    //GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
25.    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
26.    GPIO_Init(GPIOA, &GPIO_InitStruct);
27.    /*Configure GPIO pin: PA10 (USART1 RX)*/
28.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
29.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
30.    GPIO_Init(GPIOA, &GPIO_InitStruct);
31. 
32.    USART_InitStructure.USART_BaudRate = 115200;
33.    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
34.    USART_InitStructure.USART_StopBits = USART_StopBits_1;
35.    USART_InitStructure.USART_Parity = USART_Parity_No;
36.    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
37.    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
38.    USART_Init(USART1, &USART_InitStructure);
39. 
40.    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
41. 
42.    /* Enable the USARTx Receive interrupt: this interrupt is generated when the
43.         USARTx receive data register is not empty */
44.    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
45.    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
46.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
47.    NVIC_Init(&NVIC_InitStructure);
48. 
49.    /* Enable USART1 */
50.    USART_Cmd(USART1, ENABLE);
51.}
52. 
53.void USART1_IRQHandler(void) {
54.    char c;
55.    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
56.    {
57.        c = USART_ReceiveData(USART1);
58. 
59.        if ((c == 10) || (c == 13) || (c == 0) || (rxIdx >= (RXSIZE-2))) {
60.            //end of string
61. 
62.            //Check if this is a bootloader initialisation request from host:
63.            if ((c == 0) && (rxIdx == 2) && (rxStr[1] == 0xff)) {
64.                BootActivate();
65.            }
66. 
67.            //Feed data to testioHandler
68.            if ((rxStrReady == 0) && (rxIdx > 0)) {
69.                strncpy(rxStr, rxBuf, rxIdx);
70.                rxStr[rxIdx] = 0;   //Terminate!
71.                rxStrReady = 1;
72.            }
73. 
74.            rxIdx = 0;
75.            rxBuf[rxIdx] = 0;
76.        } else {
77.            rxBuf[rxIdx] = c;
78.            rxIdx ++;
79.            rxBuf[rxIdx] = 0;
80.        }
81.    }
82.}
83. 
84.void USART1_Send(char *pucBuffer, unsigned long ulCount) {
85.    while(ulCount--) {
86.        USART_SendData(USART1, *pucBuffer++);
87.        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
88.    }
89.}



Code for USART2:
001.void USART2_Init_485(void) {
002.    GPIO_InitTypeDef GPIO_InitStruct;
003.    NVIC_InitTypeDef NVIC_InitStructure;
004.    USART_InitTypeDef USART_InitStructure;
005. 
006.    USART_DeInit(USART2);
007. 
008.    /* Enable GPIO clock */
009.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
010. 
011.    /* GPIOB Periph clock enable */
012.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
013. 
014.    /* Enable USARTx clock */
015.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
016. 
017.    /* Enable the USARTx Interrupt */
018.    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
019.    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
020.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
021.    NVIC_Init(&NVIC_InitStructure);
022. 
023.    USART_InitStructure.USART_BaudRate = 9600;
024.    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
025.    USART_InitStructure.USART_StopBits = USART_StopBits_1;
026.    USART_InitStructure.USART_Parity = USART_Parity_No;
027.    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
028.    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
029. 
030.    /*Configure GPIO pin: PA2 (USART2 TX), PA1 (USART2 DE)*/
031.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1;
032.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
033.    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
034.    GPIO_Init(GPIOA, &GPIO_InitStruct);
035.    /*Configure GPIO pin: PA3 (USART2 RX)*/
036.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
037.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
038.    GPIO_Init(GPIOA, &GPIO_InitStruct);
039.    /*Configure GPIO pin: PB15 (nRS485/RS232) MUX*/
040.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
041.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
042.    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
043.    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
044.    GPIO_Init(GPIOB, &GPIO_InitStruct);
045. 
046.    GPIO_WriteBit(GPIOB, GPIO_Pin_15, 0);
047. 
048.    /* Connect PXx to USARTx_RTS *Believed to be the RS485 DE output*  */
049.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);
050.    /* Connect PXx to USARTx_Tx */
051.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
052.    /* Connect PXx to USARTx_Rx */
053.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
054. 
055.    USART_Init(USART2, &USART_InitStructure);
056. 
057.    USART_DECmd(USART2, ENABLE);
058.    USART_DEPolarityConfig(USART2, USART_DEPolarity_High);
059.    USART_SetDEAssertionTime(USART2, 0);
060.    USART_SetDEDeassertionTime(USART2, 0x1F);
061. 
062.    /* Enable USART2 */
063.    USART_Cmd(USART2, ENABLE);
064. 
065.    /* Enable the USART2 Receive interrupt: this interrupt is generated when the
066.         USART2 receive data register is not empty */
067.    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
068.}
069. 
070. 
071.void USART2_Init_232(void) {
072.    GPIO_InitTypeDef GPIO_InitStruct;
073.    NVIC_InitTypeDef NVIC_InitStructure;
074.    USART_InitTypeDef USART_InitStructure;
075. 
076.    USART_DeInit(USART2);
077. 
078.    /* Enable GPIO clock */
079.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
080. 
081.    /* GPIOB Periph clock enable */
082.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
083. 
084.    /* Enable USARTx clock */
085.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
086. 
087.    /* Enable the USARTx Interrupt */
088.    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
089.    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
090.    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
091.    NVIC_Init(&NVIC_InitStructure);
092. 
093.    USART_InitStructure.USART_BaudRate = 9600;
094.    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
095.    USART_InitStructure.USART_StopBits = USART_StopBits_1;
096.    USART_InitStructure.USART_Parity = USART_Parity_No;
097.    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
098.    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
099. 
100.    /*Configure GPIO pin: PA2 (USART2 TX), PA1 (USART2 DE)*/
101.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1;
102.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
103.    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
104.    GPIO_Init(GPIOA, &GPIO_InitStruct);
105.    /*Configure GPIO pin: PA3 (USART2 RX)*/
106.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
107.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
108.    GPIO_Init(GPIOA, &GPIO_InitStruct);
109.    /*Configure GPIO pin: PB15 (nRS485/RS232) MUX*/
110.    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
111.    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
112.    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
113.    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
114.    GPIO_Init(GPIOB, &GPIO_InitStruct);
115. 
116.    GPIO_WriteBit(GPIOB, GPIO_Pin_15, 1);
117. 
118.    /* Connect PXx to USARTx_RTS *Believed to be the RS485 DE output*  */
119.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);
120.    /* Connect PXx to USARTx_Tx */
121.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
122.    /* Connect PXx to USARTx_Rx */
123.    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
124. 
125.    USART_Init(USART2, &USART_InitStructure);
126. 
127.    USART_DECmd(USART2, DISABLE);
128.//  USART_DEPolarityConfig(USART2, USART_DEPolarity_High);
129.//  USART_SetDEAssertionTime(USART2, 10);
130.//  USART_SetDEDeassertionTime(USART2, 10);
131. 
132.    /* Enable USART2 */
133.    USART_Cmd(USART2, ENABLE);
134. 
135.    /* Enable the USART2 Receive interrupt: this interrupt is generated when the
136.         USART2 receive data register is not empty */
137.    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
138.}
139. 
140.void USART2_SendStr(char *pucBuffer) {
141.    while(*pucBuffer != 0) {
142.        USART_SendData(USART2, *pucBuffer++);
143.        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
144.    }
145.}
146. 
147.void USART2_IRQHandler(void) {
148.    char c;
149.    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
150.    {
151.        c = toupper(USART_ReceiveData(USART2));
152. 
153.        if ((c == 'X') || (c == 10) || (c == 13) || (rxRemoteIdx >= (RXSIZE-2))) {
154.            //Cancel command
155.            rxRemoteIdx = 0;
156.            rxRemote[rxRemoteIdx] = 0;
157. 
158.        } else if (c == 'T') {
159.            //Execute command
160.            if ((rxRemoteStrReady == 0) && (rxRemoteIdx > 0)) {
161.                strncpy(rxRemoteStr, rxRemote, rxRemoteIdx);
162.                rxRemoteStr[rxRemoteIdx] = 0;   //Terminate!
163.                rxRemoteStrReady = 1;
164.            }
165. 
166.            rxRemoteIdx = 0;
167.            rxRemote[rxRemoteIdx] = 0;
168. 
169.        } else {
170.            rxRemote[rxRemoteIdx] = c;
171.            rxRemoteIdx ++;
172.            rxRemote[rxRemoteIdx] = 0;
173.        }
174.    }
175.}

Outcomes