Hello
I am trying to create a standalone program in C to use the CAN to send and receive messages and display them using the printf. I use the polled examples given by Xilinx :
file:///C:/Xilinx/14.4/ISE_DS/EDK/sw/XilinxProcessorIPLib/drivers/canps_v1_01_a/examples/xcanps_polled_example.c
The program just send a message to a CAN device using the JB3 PIN and wait for an answer on JB4 PIN to display it.
Using oscilloscope I can see both send and receive on each PIN.
The problem is that the program does'nt detect the receive message so it cannot display it (it is always waiting for a message). It is stuck at this instruction :
while(XCanPs_IsRxEmpty(InstancePtr) == TRUE)
I just changed the mode from LOOPBACK to NORMAL :
XCanPs_EnterMode(CanInstPtr, XCANPS_MODE_NORMAL);
while(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_NORMAL);
I tried the interrupt example and it is the same problem to.
Can someone help me ? Here is the source code :
#include <stdio.h>
#include "platform.h"
/***************************** Include Files *********************************/
#include "xcanps.h"
#include "xparameters.h"
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define CAN_DEVICE_IDtXPAR_XCANPS_0_DEVICE_ID
/*
* Maximum CAN frame length in words.
*/
#define XCANPS_MAX_FRAME_SIZE_IN_WORDS (XCANPS_MAX_FRAME_SIZE / sizeof(u32))
#define FRAME_DATA_LENGTH tt8 /* Frame Data field length */
/*
* Message Id Constant.
*/
#define TEST_MESSAGE_IDttt2000
/*
* The Baud Rate Prescaler Register (BRPR) and Bit Timing Register (BTR)
* are setup such that CAN baud rate equals 40Kbps, assuming that the
* the CAN clock is 24MHz. The user needs to modify these values based on
* the desired baud rate and the CAN clock frequency. For more information
* see the CAN 2.0A, CAN 2.0B, ISO 11898-1 specifications.
*/
/*
* Timing parameters to be set in the Bit Timing Register (BTR).
* These values are for a 40 Kbps baudrate assuming the CAN input clock
frequency
* is 24 MHz.
*/
#define TEST_BTR_SYNCJUMPWIDTHtt1
#define TEST_BTR_SECOND_TIMESEGMENTt3
#define TEST_BTR_FIRST_TIMESEGMENTt8
/*
* The Baud rate Prescalar value in the Baud Rate Prescaler Register (BRPR)
* needs to be set based on the input clock frequency to the CAN core and
* the desired CAN baud rate.
* This value is for a 40 Kbps baudrate assuming the CAN input clock frequency
* is 24 MHz.
*/
#define TEST_BRPR_BAUD_PRESCALARt1
/************************** Function Prototypes ******************************/
int CanPsPolledExample(u16 DeviceId);
static int SendFrame(XCanPs *InstancePtr);
static int RecvFrame(XCanPs *InstancePtr);
/************************** Variable Definitions *****************************/
/*
* Buffers to hold frames to send and receive. These are declared as global so
* that they are not on the stack.
* These buffers need to be 32-bit aligned
*/
static u32 TxFrame[XCANPS_MAX_FRAME_SIZE_IN_WORDS];
static u32 RxFrame[XCANPS_MAX_FRAME_SIZE_IN_WORDS];
/* Driver instance */
static XCanPs Can;
int main()
{
tint Status;
txil_printf("CAN Polled Mode Example Test r
");
t/*
t * Run the Can Polled example, specify the Device ID that is generated
t * in xparameters.h .
t */
tStatus = CanPsPolledExample(CAN_DEVICE_ID);
tif(Status != XST_SUCCESS){
ttxil_printf("CAN Polled Mode Example Test Failedr
");
ttreturn XST_FAILURE;
t}
txil_printf("Successfully ran CAN Polled Mode Example Testr
");
treturn XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* The entry point for showing the XCanPs driver in polled mode. The example
* configures the device for internal loop back mode, then sends a Can
* frame, receives the same Can frame, and verifies the frame contents.
*
* @paramtDeviceId is the XPAR_<CANPS_instance>_DEVICE_ID value from
*ttxparameters.h
*
* @returntXST_SUCCESS if successful, otherwise driver-specific error code.
*
* @note
*
* If the device is not working correctly, this function may enter an infinite
* loop and will never return to the caller.
*
******************************************************************************/
int CanPsPolledExample(u16 DeviceId)
{
tint Status;
tXCanPs *CanInstPtr = &Can;
tXCanPs_Config *ConfigPtr;
t/*
t * Initialize the Can device.
t */
tConfigPtr = XCanPs_LookupConfig(DeviceId);
tif(CanInstPtr == NULL){
ttreturn XST_FAILURE;
t}
tStatus = XCanPs_CfgInitialize(CanInstPtr, ConfigPtr, ConfigPtr->BaseAddr);
tif(Status != XST_SUCCESS){
ttreturn XST_FAILURE;
t}
t/*
t * Run self-test on the device, which verifies basic sanity of the
t * device and the driver.
t */
tStatus = XCanPs_SelfTest(CanInstPtr);
tif(Status != XST_SUCCESS){
ttreturn XST_FAILURE;
t}
t/*
t * Enter Configuration Mode so we can setup Baud Rate Prescaler
t * Register (BRPR) and Bit Timing Register (BTR).
t */
tXCanPs_EnterMode(CanInstPtr, XCANPS_MODE_CONFIG);
twhile(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_CONFIG);
t/*
t * Setup Baud Rate Prescaler Register (BRPR) and
t * Bit Timing Register (BTR).
t */
tXCanPs_SetBaudRatePrescaler(CanInstPtr, TEST_BRPR_BAUD_PRESCALAR);
tXCanPs_SetBitTiming(CanInstPtr, TEST_BTR_SYNCJUMPWIDTH, TEST_BTR_SECOND_TIMESEGMENT, TEST_BTR_FIRST_TIMESEGMENT);
t/*
t * Enter Loop Back Mode.
t */
tXCanPs_EnterMode(CanInstPtr, XCANPS_MODE_NORMAL);
twhile(XCanPs_GetMode(CanInstPtr) != XCANPS_MODE_NORMAL);
t/*
t * Send a frame, receive the frame via the loop back and verify its
t * contents.
t */
tStatus = SendFrame(CanInstPtr);
tif(Status != XST_SUCCESS){
ttreturn Status;
t}
tStatus = RecvFrame(CanInstPtr);
treturn Status;
}
/*****************************************************************************/
/**
*
* Send a CAN frame.
*
* @paramtInstancePtr is a pointer to the driver instance
*
* @returntXST_SUCCESS if successful, a driver-specific return code if not.
*
* @note
*
* This function waits until TX FIFO has room for at least one frame before
* sending a frame. So this function may block if the hardware is not built
* correctly.
*
******************************************************************************/
static int SendFrame(XCanPs *InstancePtr)
{
tu8 *FramePtr;
tint Index;
tint Status;
t/*
t * Create correct values for Identifier and Data Length Code Register.
t */
tTxFrame[0] = (u32)XCanPs_CreateIdValue((u32)TEST_MESSAGE_ID, 0, 0, 0, 0);
tTxFrame[1] = (u32)XCanPs_CreateDlcValue((u32)FRAME_DATA_LENGTH);
t/*
t * Now fill in the data field with known values so we can verify them
t * on receive.
t */
tFramePtr = (u8 *)(&TxFrame[2]);
t//for (Index = 0; Index < FRAME_DATA_LENGTH; Index++) {
t//t*FramePtr++ = (u8)Index;
t//}
tFramePtr[0] = (u8)31;
tFramePtr[1] = (u8)32;
tFramePtr[2] = (u8)33;
tFramePtr[3] = (u8)34;
tFramePtr[4] = (u8)35;
tFramePtr[5] = (u8)36;
tFramePtr[6] = (u8)37;
tFramePtr[7] = (u8)38;
tfor(Index=0 ; Index<FRAME_DATA_LENGTH ; Index++){
ttxil_printf("send%d : %d
r", Index, FramePtr[Index]);
t}
t/*
t * Wait until TX FIFO has room.
t */
twhile(XCanPs_IsTxFifoFull(InstancePtr) == TRUE);
t/*
t * Now send the frame.
t *
t * Another way to send a frame is keep calling XCanPs_Send() until it
t * returns XST_SUCCESS. No check on if TX FIFO is full is needed anymore
t * in that case.
t */
tStatus = XCanPs_Send(InstancePtr, TxFrame);
treturn Status;
}
/*****************************************************************************/
/**
*
* This function receives a frame and verifies its contents.
*
* @paramtInstancePtr is a pointer to the driver instance.
*
* @returntXST_SUCCESS if successful, a driver-specific return code if not.
*
* @note
*
* This function waits until RX FIFO becomes not empty before reading a frame
* from it. So this function may block if the hardware is not built
* correctly.
*
******************************************************************************/
static int RecvFrame(XCanPs *InstancePtr)
{
tu8 *FramePtr;
tint Status;
tint Index;
t/*
t * Wait until a frame is received.
t */
twhile(XCanPs_IsRxEmpty(InstancePtr) == TRUE);
t/*
t * Receive a frame and verify its contents.
t */
tStatus = XCanPs_Recv(InstancePtr, RxFrame);
tif(Status == XST_SUCCESS){
tt/*
tt * Verify Identifier and Data Length Code.
tt */
ttif (RxFrame[0] !=
ttt(u32)XCanPs_CreateIdValue((u32)TEST_MESSAGE_ID, 0, 0, 0, 0))
tttreturn XST_LOOPBACK_ERROR;
ttif ((RxFrame[1] & ~XCANPS_DLCR_TIMESTAMP_MASK) != TxFrame[1])
tttreturn XST_LOOPBACK_ERROR;
tt/*
tt * Verify Data field contents.
tt */
ttFramePtr = (u8 *)(&RxFrame[2]);
tt//for (Index = 0; Index < FRAME_DATA_LENGTH; Index++) {
tt//tif (*FramePtr++ != (u8)Index) {
tt//ttreturn XST_LOOPBACK_ERROR;
tt//t}
tt//}
ttfor (Index=0 ; Index<FRAME_DATA_LENGTH ; Index++){
tttxil_printf("receive%d : %d
r", Index, FramePtr[Index]);
tt}
t}
treturn Status
Thank you very much