I am using the STM32F103ZET6 MCU and am having a weird problem where if I program and debug or program and reset my MCU the USART3 used to communicate with a slave device does not work. In debug there is no USART data going into memory from the DMA, and I have got it on a scope that the slave device is constantly sending data. I have checked:

  1. The clocks are configured at appropriate speeds.
  2. The USART is still working using USART3_getchar(0)
  3. re-initiliasing my USART3.
  4. BOOT0 pin is low in debug.
  5. The DMA channel is not being used by anything else.

I have checked the reference manual and device datasheet but am struggling to debug/check settings in code to see the difference between debug/reset run.

// Local Variables
GPIO_InitTypeDef    GPIO_InitStructure;
NVIC_InitTypeDef    NVIC_InitStructure;
USART_InitTypeDef   USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;

// Code
// Configure UART
RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3 | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);     // USART3 Periph clock enable

// Configure Pins
GPIO_InitStructure.GPIO_Pin                     =  UART3_RX_PIN;
GPIO_InitStructure.GPIO_Speed                   =  GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode                    =  GPIO_Mode_IPD;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin                     =  UART3_TX_PIN;
GPIO_InitStructure.GPIO_Speed                   =  GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode                    =  GPIO_Mode_AF_PP;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);

#if(UART3_TX_FLOW_CTS_EN    == 1)                                                       
// Enable USART3 CTS pin
GPIO_InitStructure.GPIO_Pin                     =  UART3_CTS_PIN;
GPIO_InitStructure.GPIO_Speed                   =  GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode                    =  GPIO_Mode_IN_FLOATING;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);

#if(UART3_RX_FLOW_RTS_EN    == 1)                                                       
// Enable USART3 RTS pin
GPIO_InitStructure.GPIO_Pin                     =  UART3_RTS_PIN;
GPIO_InitStructure.GPIO_Speed                   =  GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode                    =  GPIO_Mode_Out_PP;
GPIO_Init(UART3_PORT, &GPIO_InitStructure);

// initialise the RTS pin as go

st_uart3_tx_glb.timeout_timer_u16               =  UART3_TX_TIMEOUT;
while(  (uart3_tx_flg                           == 0)   &&
#if(UART3_TX_FLOW_CTS_EN    == 1)

        (mCSP_USART3_CTS_READ                   == 0)   &&
        (st_uart3_tx_glb.timeout_timer_u16      >  0)   );

//Set USART3 Clock
USART_ClockInit(USART3, &USART_ClockInitStructure);

USART_InitStructure.USART_BaudRate                  =  baud_rate_u32;
USART_InitStructure.USART_WordLength                =  USART_WordLength_8b;
USART_InitStructure.USART_StopBits                  =  USART_StopBits_1;
USART_InitStructure.USART_Parity                    =  USART_Parity_No;
#if(UART3_TX_FLOW_CTS_EN    == 1)
USART_InitStructure.USART_HardwareFlowControl       =  
USART_HardwareFlowControl_CTS;  // Enable USART3 CTS pin
USART_InitStructure.USART_HardwareFlowControl       =  
USART_InitStructure.USART_Mode                      =  USART_Mode_Rx | 
USART_Init(USART3, &USART_InitStructure);

// Enable interrupts
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);

// Enable modules

// Enable the UART3 Interupt
//  NVIC_InitStructure.NVIC_IRQChannel                      =  USART3_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=USART3_IRQ_PREM_PRI;
//  NVIC_InitStructure.NVIC_IRQChannelSubPriority   = USART3_IRQ_SUB_PRI;
//  NVIC_InitStructure.NVIC_IRQChannelCmd                   =  ENABLE;
//  NVIC_Init(&NVIC_InitStructure);

// Configure DMA
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                                  // DMA1 Periph clock enable

st_uart3_tx_glb.cnt_u8                              =  st_uart3_tx_glb.wr_index_u8;

DMA_UART3_InitStructure.DMA_PeripheralBaseAddr      =  (uint32_t)&USART3->DR;
DMA_UART3_InitStructure.DMA_MemoryBaseAddr          =  (uint32_t)uart3_rx_buffer_a_u8_glb;
DMA_UART3_InitStructure.DMA_DIR                     =  DMA_DIR_PeripheralSRC;
DMA_UART3_InitStructure.DMA_BufferSize              =  st_uart3_tx_glb.cnt_u8;
DMA_UART3_InitStructure.DMA_PeripheralInc           =  DMA_PeripheralInc_Disable;
DMA_UART3_InitStructure.DMA_MemoryInc               =  DMA_MemoryInc_Enable;
DMA_UART3_InitStructure.DMA_PeripheralDataSize      =  DMA_PeripheralDataSize_Byte;
DMA_UART3_InitStructure.DMA_MemoryDataSize          =  DMA_MemoryDataSize_Byte;
DMA_UART3_InitStructure.DMA_Mode                    =  DMA_Mode_Circular;
DMA_UART3_InitStructure.DMA_Priority                =  DMA_Priority_VeryHigh;
DMA_UART3_InitStructure.DMA_M2M                     =  DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_UART3_InitStructure);

// Enable the DMA complete Interupt
NVIC_InitStructure.NVIC_IRQChannel                      =  DMA1_Channel2_IRQn;

DMA_Cmd(DMA1_Channel2, ENABLE);
  • \$\begingroup\$ The DMA and USART cannot be halted during debug, you could get out-of-sync if you miss interrupts this way. See DBGMCU_CR. \$\endgroup\$ – Jeroen3 Oct 26 '17 at 9:08
  • \$\begingroup\$ I can see the bit definition in stm32f10x.h but I am not sure, do I need to define speicifc DBGMCU_CR bits for USART and DMA to work in debug? I don't think i've needed to do this before. I am not halting the CPU, I am simply waiting for a bit to come into the memory and halting after that. \$\endgroup\$ – ConfusedCheese Oct 26 '17 at 9:13

Local structs should be initialised, otherwise some fields can get unpredictable values:

GPIO_InitTypeDef    GPIO_InitStructure={};
NVIC_InitTypeDef    NVIC_InitStructure={};
USART_InitTypeDef   USART_InitStructure={};
USART_ClockInitTypeDef USART_ClockInitStructure={};

mCSP_USART3_RTS_PIN_GO; What does this statement do? Is it a macro or what?

These flags should be declared volatile, otherwise you can get different behaviour at different optimization settings:

while(  (uart3_tx_flg                           == 0)   &&
#if(UART3_TX_FLOW_CTS_EN    == 1)
    (mCSP_USART3_CTS_READ                   == 0)   &&
    (st_uart3_tx_glb.timeout_timer_u16      >  0)   );

It was that USART3 is on APB1 and not APB2 clock and was therefore not being enabled but in the bootloader the APB1 USART3 clock was being enabled.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.