I've been working with STM Cortex-M3, M4 and M7 boards for around eight years using TrueStudio.
The current project is a Chinese Cortex-M4 derivative (TKM32F499GT@240MHz) board with LCD and ESP8266 WiFi module. The ESP is programmed via UART2, and there is a UART4 for general I/O. UART1 is the main serial port and is fully functional.
The board came with a variety of small sample code projects created with Keil MDK. These projects include the build binary that can be loaded on to the board for testing. The Keil sources were ported to TrueSTUDIO 9.2. This required making a generic (i.e. not a STM target) M4 project and adjusting the startup .s and linker script files as needed. I have built ten working apps of varying complexity, including LCD init, graphics, USB CDC, HID and MSD, capacitive touch support and some GPIO control. Please note this code does not use the STM HAL libraries: it uses a version of CMSIS.
So here's the problem.
One of the sample apps configures the ESP8266 via UART2 (AT commands). The Keil binary (7KB) loads and UART1 reports success and immediate expected responses from the ESP via UART2. I can connect a Virtual comm device on to UART2 to monitor the instructions received and sent.
Building the same code in TrueSTUDIO creates a 30KB binary which runs and writes the expected text to UART1. The larger size is probably because my project is Debug mode. What happens is that UART2 is not responding. The UART2 registers are being loaded with the correct info as far as I can tell. Data is arriving at the UART2->TDR but seems not to be transmitted. All the other UART registers have the correct (AFAIK) settings too. The UART2 RCC clock is enabled, with essentially the same code as UART1.
Out of curiosity (and frustration...) I made a minimal new app that wrote text to UART4, with a Virtual comm device attached. Same problem, data is arriving at the UART4->TDR but is not being transmitted.
It's almost like the UARTs are not being enabled in some obscure way. As said above, the Keil binary works fine. It's obviously something pretty obscure, but after more than a week I'm really stuck.
Any ideas where to look next? All suggestions are most appreciated.
******** some code snippets: really the most basic stuff ******
UART_STATUS UART1_Init(int BaudRate)
{
UART_STATUS rtnStatus = UART_INIT_OK;
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //uart1_tx PA9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //uart1_rx PA10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Now we set the AF mode
GPIO_PinAFConfig(GPIOA, GPIO_Pin_9 | GPIO_Pin_10, GPIO_AF_UART_1); //PA9 PA10
RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//
UART_InitStructure.UART_StopBits = UART_StopBits_1;//
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART1, &UART_InitStructure);
UART_Cmd(UART1, ENABLE); //UART
UART_ClearITPendingBit(UART1, 0xff);
return rtnStatus;
}
//
// Pins available on connector P8
//
UART_STATUS UART4_Init(int BaudRate)
{
UART_STATUS rtnStatus = UART_INIT_OK;
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //uart4_tx PD7
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //uart4_rx PD6
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_Pin_7 | GPIO_Pin_6, GPIO_AF_UART_2345); // PD7 PD6
RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART4, ENABLE);
UART_InitStructure.UART_BaudRate = BaudRate; //
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//
UART_InitStructure.UART_StopBits = UART_StopBits_1;//
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_Mode = UART_Mode_Tx|UART_Mode_Rx; //
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_Init(UART4, &UART_InitStructure);
UART_Cmd(UART4, ENABLE); //UART
UART_ClearITPendingBit(UART4, 0xff);
return rtnStatus;
}
int main(void)
{
uint8_t k;
RemapVectorTable();
SystemClk_HSEInit(RCC_PLLMul_20);// PLL 12MHz*20=240MHz == SYSCLK
RCC_PCLK1Config(RCC_HCLK_Div4); // sets APB1 to 60MHz
RCC_PCLK2Config(RCC_HCLK_Div2); // sets APB2 to 120MHz
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
UART1_Init(460800); //
LED_Init();
LCD_Initial();
// TIM8 is on APB1 @ 60MHz, Div 6000 = 10KHz, 1000 = 1Hz
TIM8_Config(6000,10000);
LCD_DrawStartScreen();
LCD_ShowFWrev();
UART4_Init(115200);
send_str("External INT Demo ready\r\nTry USART4 ...\r\n"); // to UART1
send4_str("Send to USART4 ready?\r\n"); // to UART4
while(1)
{
// just loop ...
}
}
The USART4 ports are ID'd from the board schematic. The Virtual USB comm ports are connected to USART1 and USART4. I expected that just sending some text to USART4 would work, but nothing. I do get a very occasional garbage character which usually means the baud rate is wrong. I've looked at the UART4 register settings and it all seems correct as described in the TK32F499 user manual (455 pages).