AnsweredAssumed Answered

Stm32F103CB USART DMA RING BUFFER

Question asked by grozea.ion on Oct 14, 2016
Latest reply on Oct 31, 2016 by ForumSTM32.ForumSTM3
Hello all,

I am trying to implement a ring buffer to use it with USART3 on RX (if possible on TX) to communicate with and XBEE. So far i have the following code

USART 3 Init
void myUSART3_Init(void)
{
    USART_InitTypeDef USART_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART3, &USART_InitStructure);
 
    /* Enable USART3 */
    USART_Cmd(USART3, ENABLE);
}
GPIO Init

void myGPIO_Init(uint8_t mode)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    /* ADC Pins
    PA0 ------> Read_Battery
    PA2 ------> Read_Sensor
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
    //Cmd_Battery, Cmd_Sensor, Focus2, Shutter2, Focus1, Shutter1, CS
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* ADC Pins
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2;//0 is the battery and 2 is the sensor value
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    */
    /**USART1 GPIO Configuration
    PA9 ------> USART1_TX
    PA10------> USART1_RX
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
 
    switch(mode)
    {
    case 0://Output for valve sensor
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        break;
    case 1://Input for projectile sensor
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        break;
    case 2://PWM for motor sensor T3 CH3,4
        GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;
        break;
    }
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    /* setup SCL and SDA pins
     * You can connect I2C1 to two different
     * pairs of pins:
     * 1. SCL on PB6 and SDA on PB7
     * 2. SCL on PB8 and SDA on PB9
     */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;// we are going to use PB6 and PB7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;// set pins to alternate function
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    /**USART3 GPIO Configuration
    PB10 ------> USART3_TX
    PB11 ------> USART3_RX
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    /*
    SPI2 GPIO Configuration
    PB13 ------> SPI2_SCK
    PB14 ------> SPI2_MISO
    PB15 ------> SPI2_MOSI
    */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

The DMA Init
#define Buff_Len 64
uint16_t ADCBuffer[2];
uint8_t TxBuffer[Buff_Len];
uint8_t RxBuffer[Buff_Len];
CircularBuffer _rxBuffer;
void buffer_init(DMA_Channel_TypeDef* husart)
{
    _rxBuffer.buffer = (uint8_t *)RxBuffer;
    _rxBuffer.tailPtr = (uint8_t *)RxBuffer;
    _rxBuffer.myDMAChannel = husart;
}
 
uint8_t buffer_available(void)
{
    volatile uint8_t const* head = _rxBuffer.buffer + Buff_Len - _rxBuffer.myDMAChannel->CNDTR;
    volatile uint8_t const* tail = _rxBuffer.tailPtr;
    if (head >= tail)
    {
        return head - tail;
    }
    else
    {
        return head - tail + Buff_Len;
    }
}
 
uint8_t buffer_read(void)
{
    uint8_t ret = *_rxBuffer.tailPtr++;
    if (_rxBuffer.tailPtr >= _rxBuffer.buffer + Buff_Len)
    {
        _rxBuffer.tailPtr -= Buff_Len;
    }
    return ret;
}
 
void DMA1_Channel2_IRQHandler(void) // USART1_TX
{
  /* Test on DMA Transfer Complete interrupt */
  if (DMA_GetITStatus(DMA1_IT_TC2))
  {
    /* Clear DMA Transfer Complete interrupt pending bit */
    DMA_ClearITPendingBit(DMA1_IT_TC2);
 
    /* ... */
  }
}
 
void DMA1_Channel3_IRQHandler(void) // USART1_RX
{
  /* Test on DMA Transfer Complete interrupt */
  if (DMA_GetITStatus(DMA1_IT_TC3))
  {
    /* Clear DMA Transfer Complete interrupt pending bit */
    DMA_ClearITPendingBit(DMA1_IT_TC3);
 
    /* ... */
  }
}
void myDMA_Init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    /* Reset DMA1 channel 1 to default values */
    DMA_DeInit(DMA1_Channel1);
    /* DMA1 channel 1 configuration */
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //Address of peripheral the DMA must map to
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = 2;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    /* Enable DMA1 channel1 */
    DMA_Cmd(DMA1_Channel1, ENABLE);
 
    /* Reset DMA1 channe2 and 3 to default values */
    DMA_DeInit(DMA1_Channel2);//TX
 
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = Buff_Len;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);
    USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
 
    DMA_DeInit(DMA1_Channel3);//RX
 
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = Buff_Len;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
 
    DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
 
    DMA_Cmd(DMA1_Channel2, ENABLE);
    DMA_Cmd(DMA1_Channel3, ENABLE);
    buffer_init(DMA1_Channel3);
}
 
uint16_t getBattery(void)
{
    return ADCBuffer[0];
}
uint16_t getSensor(void)
{
    return ADCBuffer[1];
}
and in my main i use

void myUART_3()
{
    USART_puts(".\r\n");
    uint8_t keep[32];
    uint16_t cSum = 0;
    uint8_t crtByte, cnt = 0;
    uint8_t aSize = buffer_available();
        if(aSize >= 17) //a command frame has 17 bytes
        {
            USART_puts("We have %d bytes available");//\r\n
            USART_SendData_Numeric(aSize);
            if(buffer_read() == 0x7e) //byte 0
            {
                crtByte = buffer_read();    //discard byte 1
                cnt = buffer_read() ;// get message length  byte 2
                for(uint8_t j=0; j<cnt;j++)
                {
                    crtByte = buffer_read();
                    cSum +=crtByte;
                    if(j >= 12)//from here we have the data
                    {
                        keep[j-12] = crtByte;
                    }
                }
                cSum &= 0xFF;//keep only last 8 bits
                cSum = 0xFF - cSum;
                crtByte = buffer_read();
            }
        }
}
 
void myNVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    /*NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);*/
 
      /* Configure the Priority Group to 2 bits */
 
      /* Enable the USART1 TX DMA Interrupt */
      NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
 
      /* Enable the USART1 RX DMA Interrupt */
      NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
}
 
void Delay(uint16_t val);
void init_RCC(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//enable DMA clock
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//Set ADC clock to 12MHz
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);//Enable ADC, GPIOA and GPIOB clock
}
int main(void)
{
    init_RCC();
    myNVIC_Configuration();//Do i need it in DMA mode?
    myGPIO_Init(2);
    myDMA_Init();
    myADC_Init();
    //myI2C1_Init();
    //mySPI2_Init();
    myUSART3_Init();
    myUSART1_Init();
    //config_PWM();
    //myEXTI_Init();
    BatteryOn;
    SensorOn;
    //MS561101BA_init(0xEC);
    USART_puts("End INIT...\r\n");
    int32_t w = 0;
    while(1)
    {
        myUART_3();
        Delay(500);
 
    }
}
 
void Delay(uint16_t val)
{
    volatile uint32_t i, end;
    end = val * 2000;
    for (i=0; i != end; i++);
}

Basically i know that there is no HW problem because the USART 3 is working, i do not know if the DMA setup for usart3 or the functions that handle the ring buffer are wrong. Can someone help me to solve this?
Thank you

Outcomes