Other Parts Discussed in Thread: TMDSICE3359, AM3359
Hello,
We are currently developing a driving simulator. In this purpose, we needed a device used as interface between all the components of the simulator.
We bought the TMDSICE3359 : http://www.ti.com/tool/tmdsice3359 as development board.
We communicate with a CANOpen device, we decided to use the Starterware library (AM335X_StarterWare_02_00_01_01) because of the proposed DCAN example.
But unfortunately after trying, we couldn’t make the dcanTxRx example to work.
We asked on the forum and we were told by an employee that it might exist an issue with our board.
Thus (because we needed to continue our work), we switched to the SYS/BIOS framework. In there, we found another implementation of the DCAN derived from the Starterware library.
Using that, we were able to do the biggest part of the work, the DCAN TX is working but impossible the make the DCAN RX work.
What we want : is a function « void RXdcan() » waiting to return the first received data frame read by the board.
What we have : is a function waiting for the receiving interrupt to read the data but there is no interrupt when we feed the board with data.
As we have the TXdcan working (because of the differential pair), we know that there is no hardware issue but only something wrong in our software.
We are not sure of how to configure the Receive Message Object and how to make it work
You will find the main piece of code below :
#include <stdio.h>
#include <types.h>
#include <unistd.h>
#include "appl_cnfg.h"
#include "osdrv_utils.h"
#include "osdrv_version.h"
#include "board.h"
#include "board_support.h"
#include "hw_types.h"
#include "interrupt.h"
// UART
#include "console_utils.h"
// DCAN
#include "dcan.h"
/******************************************************************************
** INTERNAL MACRO DEFINITIONS
******************************************************************************/
#define CAN_DATA_BYTES_MAX_SIZE (8u)
#define CAN_NUM_OF_MSG_OBJS (64u)
#define CAN_RX_MSG_ID (0u)
#define CAN_TX_MSG_ID (0u)
#define DCAN_ERROR_OCCURED (0x8000u)
#define DCAN_NO_INT_PENDING (0x00000000u)
#define DCAN_BIT_RATE (1000000u)
#define DCAN_IN_CLK (24000000u)
can_frame entry;
/******************************************************************************
** FUNCTION DEFINITIONS
******************************************************************************/
static void ConfigureDCAN(void){
/* Enable the DCAN0 module clock */
DCANModuleClkConfig();
/* Perform the pinmux for DCAN0 */
DCANPinMuxSetUp(0);
/* Initialize the DCAN message RAM */
DCANMsgRAMInit(0);
/* Reset the DCAN module */
DCANReset(SOC_DCAN_0_REGS);
/* Enter the Initialization mode of CAN controller */
DCANSetMode(SOC_DCAN_0_REGS, DCAN_MODE_INIT);
/* Configure the bit timing values for CAN communication */
CANSetBitTiming(SOC_DCAN_0_REGS, DCAN_IN_CLK, DCAN_BIT_RATE);
/* Start the CAN transfer */
DCANSetMode(SOC_DCAN_0_REGS, DCAN_MODE_NORMAL);
/* Enable the error interrupts */
DCANIntrEnable(SOC_DCAN_0_REGS, DCAN_INTR_MASK_ERROR);
/* Enable the interrupt line 0 of DCAN module */
DCANIntrLineEnable(SOC_DCAN_0_REGS, DCAN_INTR_LINE_NUM_0, TRUE);
}
static void RXDCAN(unsigned int rxID, uint32_t * rxdata, int dlc){
entry.flag = DCAN_MSG_DIR_RX;
entry.id = rxID;
entry.dlc = dlc;
CANMsgObjectConfig(SOC_DCAN_0_REGS, &entry);
uint32_t msgNum;
while(1){
msgNum = DCANIntrStatus(SOC_DCAN_0_REGS, DCAN_INTR_LINE_NUM_0);
if((msgNum != DCAN_NO_INT_PENDING) && ((msgNum != DCAN_ERROR_OCCURED))) {
/* Get the number of the message object which caused the interrupt */
msgNum = DCANIntrStatus(SOC_DCAN_0_REGS, DCAN_INTR_LINE_NUM_0);
CONSOLEUtilsPrintf("%d\n",msgNum);
if((msgNum >= (CAN_NUM_OF_MSG_OBJS/2)) && (msgNum < CAN_NUM_OF_MSG_OBJS)){
/* Read a received message from message RAM to interface register */
CANReadMsgObjData(SOC_DCAN_0_REGS, msgNum, rxdata, DCAN_IF_REG_NUM_2);
/* Clear the Interrupt pending status */
CANClrIntPndStat(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_2);
/* Disable the receive interrupt of the message object */
CANRxIntDisable(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_2);
/* Invalidate the receive message object */
CANInValidateMsgObject(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_2);
CONSOLEUtilsPrintf("RX\n");
break;
}
if(msgNum < (CAN_NUM_OF_MSG_OBJS/2)){
/* Clear the Interrupt pending status */
CANClrIntPndStat(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_1);
/* Disable the transmit interrupt of the message object */
CANTxIntDisable(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_1);
/* Invalidate the receive message object */
CANInValidateMsgObject(SOC_DCAN_0_REGS, msgNum, DCAN_IF_REG_NUM_1);
CONSOLEUtilsPrintf("TX\n");
}
else {
CONSOLEUtilsPrintf("ERROR\n");
}
}
}
}
static void TXDCAN(unsigned int txID, uint32_t * txdata, int dlc){
entry.flag = DCAN_MSG_DIR_TX;
entry.id = txID;
entry.dlc = dlc;
entry.data = txdata;
CANMsgObjectConfig(SOC_DCAN_0_REGS, &entry);
}
static void StartDRIVER(void){
// NMT Start Remote Node
uint32_t data1 = 0x2001;
TXDCAN(0x000,&data1,2);
// set the DRIVER to RUN
uint32_t data2 = 0x000F;
TXDCAN(0x220,&data2,2);
// set the DRIVER to PROFILE TORQUE
uint32_t data3[2] = {0x0060602F, 0x000004};
TXDCAN(0x620,&data3,7);
}
static void WriteTorque(double trq){
// INITIALIZATION TORQUE = 0;
uint32_t data[2] = {0x0060712B, 0x000000};
// set TORQUE to HEX data
double trqpercent = trq/10.0*100;
double temp = trqpercent*10;
data[2] = 0;
// Write TORQUE
TXDCAN(0x620,&data,7);
}
void taskFxn(){
int init = 0;
char t_str[50];
char theta_str[50];
char torque_str[50];
double theta,thetap,thetapp;
double torque;
/* Initialize the BOARD & LCD */
BOARDInit(NULL);
Board_pinMuxConfig(am335xIceV2Mux);
board_init(BOARD_LCD_DISPLAY);
Board_setLCDScroll(0);
Board_clearLCDString();
Board_setLCDString((uint8_t *) "TFE_HAPTIC", 0);
Board_setLCDString((uint8_t *) "HAPTIC_ICE V1", 1);
Board_setLCDScroll(0);
/* Initialize the UART console */
CONSOLEUtilsInit();
CONSOLEUtilsSetType(CONSOLE_UTILS_TYPE_UART);
CONSOLEUtilsPrintf("TI Industrial SDK Version - ");
CONSOLEUtilsPrintf(IND_SDK_VERSION);
CONSOLEUtilsPrintf("\n\rDevice name \t: ");
CONSOLEUtilsPrintf(SOCGetSocFamilyName());
CONSOLEUtilsPrintf("\n\rChip Revision \t: ");
CONSOLEUtilsPrintf(Board_getChipRevision());
sprintf(t_str, "%d MHz", Board_getArmClockRate());
CONSOLEUtilsPrintf("\n\rARM Clock rate \t: ");
CONSOLEUtilsPrintf(t_str);
CONSOLEUtilsPrintf("\n\rHAPTIC_ICE SOFTWARE on ICE AM3359 V2 EVM BOARD\n");
/* Configure DCAN to be usable */
ConfigureDCAN();
/* Send CAN FRAMES to initialize DRIVER */
StartDRIVER();
uint32_t testRX;
RXDCAN(0x000, &testRX, 8);
CONSOLEUtilsPrintf("%x\n",testRX);
while(init != 1)
CONSOLEUtilsScanf("%d", &init);
theta = 0.35;
thetap = 1.42;
thetapp = 97.68;
usleep(10);
while(init == 1){
// RECEPTION DES COORDONNES DU DRIVER
// CONVERSION ET ENVOI DES COORDONNEES
sprintf(theta_str, "%f %f %f \n", theta, thetap, thetapp);
CONSOLEUtilsPrintf("%s",theta_str);
// RECEPTION DU COUPLE
CONSOLEUtilsScanf("%s", &torque_str);
torque = atof(torque_str);
sprintf(t_str, "TORQUE: %.2f Nm", torque);
// AFFICHAGE DU COUPLE
Board_setLCDScroll(0);
Board_clearLCDString();
Board_setLCDString((uint8_t *)"HAPTIC_ICE V1", 0);
Board_setLCDString((uint8_t *) t_str, 1);
Board_setLCDScroll(0);
// ENVOI DU FEEDBACK AU DRIVER
WriteTorque(1);
}
}
int main(){
Task_Handle task;
Error_Block eb;
SDKMMUInit(applMmuEntries);
Error_init(&eb);
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL){
printf("Task_create() failed!\n");
BIOS_exit(0);
}
BIOS_start();
return(0);
}
Thank you for the help,
Nicola De Lellis