STM32F103ZET6 USART con DMA se comporta de manera diferente en la ejecución de depuración y reinicio

1

Estoy utilizando el MCU STM32F103ZET6 y tengo un problema extraño en el que si programa y depuro o programa y reinicio mi MCU, el USART3 utilizado para comunicarse con un dispositivo esclavo no funciona. En la depuración no hay datos USART en la memoria del DMA, y tengo un alcance en el que el dispositivo esclavo está enviando datos constantemente. He comprobado:

  1. Los relojes están configurados a velocidades apropiadas.
  2. El USART sigue funcionando usando USART3_getchar (0)
  3. reiniciando mi USART3.
  4. El pin BOOT0 es bajo en depuración.
  5. El canal DMA no está siendo utilizado por ninguna otra cosa.

He revisado el manual de referencia y la hoja de datos del dispositivo, pero estoy luchando para depurar / verificar las configuraciones en el código para ver la diferencia entre la ejecución de la depuración / reinicio.

// 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);
#endif

#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);

mCSP_USART3_RTS_PIN_GO;                                                             
// initialise the RTS pin as go
#endif

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)   &&
#endif
        (st_uart3_tx_glb.timeout_timer_u16      >  0)   );

//Set USART3 Clock
USART_ClockStructInit(&USART_ClockInitStructure);
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
#else
USART_InitStructure.USART_HardwareFlowControl       =  
USART_HardwareFlowControl_None;
#endif
USART_InitStructure.USART_Mode                      =  USART_Mode_Rx | 
USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);

// Enable interrupts
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);

// Enable modules
USART_Cmd(USART3, ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);

// 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_DeInit(DMA1_Channel2);
DMA_StructInit(&DMA_UART3_InitStructure);
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;
NVIC_Init(&NVIC_InitStructure);

DMA_Cmd(DMA1_Channel2, ENABLE);
    
pregunta ConfusedCheese

2 respuestas

1

Era que USART3 está en APB1 y no en APB2 y, por lo tanto, no estaba habilitado, pero en el cargador de arranque, el reloj APB1 USART3 estaba habilitado.

    
respondido por el ConfusedCheese
1

Las estructuras locales deben inicializarse, de lo contrario, algunos campos pueden obtener valores impredecibles:

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

mCSP_USART3_RTS_PIN_GO; ¿Qué hace esta declaración? ¿Es una macro o qué?

Estas banderas deben declararse volatile , de lo contrario, puede obtener diferentes comportamientos en diferentes configuraciones de optimización:

while(  (uart3_tx_flg                           == 0)   &&
#if(UART3_TX_FLOW_CTS_EN    == 1)
    (mCSP_USART3_CTS_READ                   == 0)   &&
#endif
    (st_uart3_tx_glb.timeout_timer_u16      >  0)   );
    
respondido por el berendi

Lea otras preguntas en las etiquetas