AnsweredAssumed Answered

STM3210c-EVAL CAN Transmission issue

Question asked by baguma.gerald on May 20, 2013
Hello,

i am having problems with making the CAN bus work on the STM3210c-EVAL board. Am using FreeRTos as the RTOS. The CAN driver keeps on returning status pending and it never succeeds  to send the message.

The CAN_TransmitStatus()  function from the driver always returns pending and then eventually returns the error code 0x02.

the code listing are the init functions for the CAN
#include "stdio.h"
#include "stm32f10x.h"
#include "CAN_helper.h"
 
 
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "setup.h"
#include "assert.h"
 
 
/* Private variables ---------------------------------------------------------*/
CAN_InitTypeDef        CAN_InitStructure;
CAN_FilterInitTypeDef  CAN_FilterInitStructure;
GPIO_InitTypeDef  GPIO_InitStructure;
NVIC_InitTypeDef  NVIC_InitStructure;
 
 
/******************************************************************************
* Function      : CAN_Config
* Description   : Configures CAN1
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void CAN_Config(void)
{
     
    /* Configure CAN1 and CAN2 IOs **********************************************/
  /* GPIOB, GPIOD and AFIO clocks enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB, ENABLE);
     
     /* Configure CAN1 RX pin */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_Init(GPIOD, &GPIO_InitStructure);
    /* Configure CAN1 TX pin */
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOD, &GPIO_InitStructure);
     /* Remap CAN1*/
     GPIO_PinRemapConfig(GPIO_Remap2_CAN1 , ENABLE);
     /* Configure CAN1 **************************************************/
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 , ENABLE);
     
    /* Set the CAN1 regs to their default values */
  CAN_DeInit(CAN1);
     
    CAN_Module_Init();
     
    CAN_Filter_Setup();
     
    CAN_TX_Init();
     
    CAN_RX_Init(&RxMessage);
     
    CAN_Set_MsgId();
}
 
 
/******************************************************************************
* Function      : CAN_Module_Init
* Description   : Configures CAN1
* Parameters    :   Sets different modes and bit rate  
* Returns           : -
******************************************************************************/
void CAN_Module_Init(void)
{
    /* Struct init*/
     
  CAN_StructInit(&CAN_InitStructure);
     
    // Configure the parameters of the CAN init structure
    CAN_InitStructure.CAN_TTCM = DISABLE; //disable the time triggered CAN
    CAN_InitStructure.CAN_ABOM = DISABLE; //disable automatic bus management
    CAN_InitStructure.CAN_AWUM = DISABLE; // disable automatic wake-up mode
    CAN_InitStructure.CAN_NART = DISABLE; // disable the no-automatic retransmission mode
    CAN_InitStructure.CAN_RFLM = DISABLE; // disable the Receive FIFO Locked mode
    CAN_InitStructure.CAN_TXFP = ENABLE;    // Enable the transmit FIFO priority
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; // Mode = normal
     
    // Setup CAN bit rate
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;  // SJW = 1 tq
  CAN_InitStructure.CAN_BS1 = CAN_BS1_12tq; //CAN_BS1_3tq;  // 3 tq in BS1
  CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq; //CAN_BS2_2tq;
    CAN_InitStructure.CAN_Prescaler = 8; // 48; // Baud rate prescaler
     
     CAN_Init(CAN1,&CAN_InitStructure);
     
}
 
 
/******************************************************************************
* Function      : CAN_Filter_Setup
* Description   : Sets the filters and masks for the receive buffers
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void CAN_Filter_Setup(void)
{
       /*CAN1 filter init */
   CAN_FilterInitStructure.CAN_FilterNumber = 1;
   CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; // Mask mode - Specific bits must match the filter
   CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
   CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
   CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
   CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
   CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;    // No mask?
   CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;    // Use FIFO 0
   CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;   // Enable the filter
   CAN_FilterInit(&CAN_FilterInitStructure);
}
 
 
/******************************************************************************
* Function      : CAN_TX_Init
* Description   : Transmit initialization
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void CAN_TX_Init(void)
{
     TxMessage.IDE = CAN_ID_STD;    // Use standard ID
     TxMessage.DLC = 8;     //
     TxMessage.StdId = 0x60;        // Set ID (dynamic!)
     TxMessage.RTR = CAN_RTR_DATA;  // Data frame
}
 
 
/******************************************************************************
* Function      : NVIC_Config
* Description   : Configures the NVIC for CAN
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void NVIC_Config(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
 
 
/******************************************************************************
* Function      : CAN_RX_Init
* Description   : Receive initialization
* Parameters    :   RxMessage   -      
* Returns           : -
******************************************************************************/
void CAN_RX_Init(CanRxMsg *RxMessage)
{
    uint8_t i = 0;
 
  RxMessage->StdId = 0;
  RxMessage->IDE = CAN_ID_STD;
  RxMessage->DLC = 0;
  RxMessage->FMI = 0;
  for (i = 0; i < 8; i++)
  {
    RxMessage->Data[i] = 0;
  }
}

The Transmit functions are shown below

#include <stdio.h>
 
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
#include "setup.h"
#include "assert.h"
#include "GLCD.h"
#include "stm3210c_eval_ioe.h"
#include "stm32f10x_can.h"
#include    "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "misc.h"
 
#include "motordriver.h"
#include "display_helper.h"
#include "CAN_helper.h"
/*-----------------------------------------------------------*/
 
xSemaphoreHandle lcdLock;
 
/* Global variables -------------------------------------------------------------*/
xSemaphoreHandle MotorDataMutex;
uint8_t State0,State1, State2;
unsigned int currentScreen, requestedScreen;
 
//shared buffers
CanMsg RecvBuffer[2];
 
 
CanTxMsg TxMessage;
CanRxMsg RxMessage;
 
MotorConfVal motorData[3];
 
ButtonData currentButtons[8];
u8 btnCnt;
 
 
void Delay(void);
     
 
/******************************************************************************
* Function      : CAN_Set_MsgId
* Description   : Sets the message ID
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void CAN_Set_MsgId(void)
{
    RecvBuffer[0].Id = ID_MOTOR0_STATUS_ID;
    RecvBuffer[1].Id = ID_MOTOR1_STATUS_ID;
     
    //TransBuffer[0].Id = ID_MOTOR0_CTRL_ID;
    //TransBuffer[1].Id = ID_MOTOR0_CTRL_ID;
}
 
 
/******************************************************************************
* Function      : CAN_Recv_Msg
* Description   : Receives message from the CAN bus and update struct
* Parameters    :   -  
* Returns           : -
******************************************************************************/
void CAN_Recv_Msg(void)
{
    int i;
     
    CanMsg newMsg;
     
    CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);
     
    for(i=0;i<8;i++)
    {      
        newMsg.data[i]=RxMessage.Data[i];
    }
         
    // Put it in receive buffer
    switch(RxMessage.StdId)
    {
        case ID_MOTOR0_STATUS_ID:
                for(i=0;i<8;i++)
                {
                    RecvBuffer[0].data[i] = newMsg.data[i];
                }
            break;
             
            case ID_MOTOR1_STATUS_ID:
                for(i=0;i<8;i++)
                {
                    RecvBuffer[1].data[i] = newMsg.data[i];
                }
                    break;
        }
}
 
 
/******************************************************************************
* Function      : CAN_Trans_Msg
* Description   : Transmits CAN control messages
* Parameters    :   Msg -   Message ID 
* Returns           : -
******************************************************************************/
void CAN_Trans_Msg(MotorConfVal Msg)
{
    uint8_t TransmitMailbox = 0;
    uint8_t status = 0;
    uint16_t i =0;
 
    TxMessage.StdId     = Msg.Id;
    TxMessage.ExtId = 0;   
    TxMessage.RTR = CAN_RTR_DATA;  
    TxMessage.IDE = CAN_ID_STD;
    TxMessage.DLC = 8;
    TxMessage.Data[0] = Msg.speed;
    TxMessage.Data[1] = Msg.mode;
    TxMessage.Data[2] = Msg.direction;
     
    if (Msg.Id == 0x20)
    {
        TxMessage.Data[3] = 0x20;
    }
    else
    {
        TxMessage.Data[3] = 0x30;
    }
     
    TxMessage.Data[4] = 0;
    TxMessage.Data[5] = 0; 
    TxMessage.Data[6] = 0; 
    TxMessage.Data[7] = 0; 
 
    TransmitMailbox = CAN_Transmit(CAN1,&TxMessage);
     
    while((status != CANTXOK) && (i != 0xFFFF))              
  {
    status = CAN_TransmitStatus(CAN1, TransmitMailbox);
    i++;   
  }
     
}
 
 
 
/******************************************************************************
* Function      : CommTask
* Description   : Manage the communication of the motors
* Parameters    :   -  
* Returns           : -
******************************************************************************/
static void CommTask(void *params)
{
      
    while(1)
    {
        xSemaphoreTake( MotorDataMutex, portMAX_DELAY );
         
        /*Receive a messages from the CAN network*/
         
        /*Send a messages to  the CAN network*/
        //send control for the stepper motor
        CAN_Trans_Msg(motorData[STP_MOTOR]);
        vTaskDelay(10 / portTICK_RATE_MS);
            //send command for the DC motor
        CAN_Trans_Msg(motorData[DC_MOTOR]);
        vTaskDelay(10 / portTICK_RATE_MS); 
         //give back resource
         
        State0 = CAN_TransmitStatus(CAN1, 0 );
        State1 = CAN_TransmitStatus(CAN1, 1 );
        State2 = CAN_TransmitStatus(CAN1, 2 );
//     
        CAN_Recv_Msg();
        xSemaphoreGive( MotorDataMutex );
     
     vTaskDelay(100 / portTICK_RATE_MS);
    }
     
}
 
int main( void )
{
  prvSetupHardware();
  IOE_Config();
 
   
    initMotors();
     
    NVIC_Config();
    CAN_Config();
    /* IT Configuration for CAN1 */ 
  CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
//  CAN_ITConfig(CAN1, CAN_IT_RQCP0, ENABLE);
//  CAN_ITConfig(CAN1, CAN_IT_RQCP1, ENABLE);
//  CAN_ITConfig(CAN1, CAN_IT_RQCP2, ENABLE);
     
    MotorDataMutex = xSemaphoreCreateMutex();
    lcdLock = xSemaphoreCreateMutex();
    /*********************************************
    *BLDC driver init
    **********************************************/
    BLDCDriverInit();
    initDisplay();
     
    /********************************************
    *BLDC interface test
    *Direction, Brake and Enable set use the three leds pin
    **************************************************/
//  SetBLDCDirection(1);
//  SetBLDCBrake(1);
//  EnableBLDCMotor(1);
//  SetBLDCSpeed(100);
     
     
  xTaskCreate(lcdTask, "lcd", 100, NULL, 1, NULL);
  //xTaskCreate(ledTask, "led", 100, NULL, 1, NULL);
    xTaskCreate(buttonPressTask, "buttonPress", 100, NULL, 1, NULL);
    xTaskCreate(CommTask, "Communication", 1000, NULL, 1, NULL );
 
  vTaskStartScheduler();
 
  assert(0);
  return 0;                 // not reachable
}


Outcomes