Example #1
0
/* Copy message to CAN module - internal usage only.
 *
 * @param CANbaseAddress CAN module base address
 * @param dest Pointer to CAN module transmit buffer
 * @param src Pointer to source message
 */
static void CO_CANsendToModule(uint16_t CANbaseAddress, __eds__ CO_CANrxMsg_t *dest, CO_CANtx_t *src){
    uint8_t DLC;
    __eds__ uint8_t *CANdataBuffer;
    uint8_t *pData;
    volatile uint16_t C_CTRL1old;

    /* CAN-ID + RTR */
    dest->ident = src->ident;

    /* Data lenght */
    DLC = src->DLC;
    if(DLC > 8) DLC = 8;
    dest->DLC = DLC;

    /* copy data */
    CANdataBuffer = &(dest->data[0]);
    pData = src->data;
    for(; DLC>0; DLC--) *(CANdataBuffer++) = *(pData++);

    /* control register, transmit request */
    C_CTRL1old = CAN_REG(CANbaseAddress, C_CTRL1);
    CAN_REG(CANbaseAddress, C_CTRL1) = C_CTRL1old & 0xFFFE;     /* WIN = 0 - use buffer registers */
    CAN_REG(CANbaseAddress, C_TR01CON) |= 0x08;
    CAN_REG(CANbaseAddress, C_CTRL1) = C_CTRL1old;
}
Example #2
0
void CO_CANsetNormalMode(uint16_t CANbaseAddress){
    uint16_t C_CTRL1copy = CAN_REG(CANbaseAddress, C_CTRL1);

    /* set REQOP = 0x0 */
    C_CTRL1copy &= 0xF8FF;
    CAN_REG(CANbaseAddress, C_CTRL1) = C_CTRL1copy;

    /* while OPMODE != 0 */
    while((CAN_REG(CANbaseAddress, C_CTRL1) & 0x00E0) != 0x0000);
}
Example #3
0
void CO_CANsetConfigurationMode(uint16_t CANbaseAddress){
    uint16_t C_CTRL1copy = CAN_REG(CANbaseAddress, C_CTRL1);

    /* set REQOP = 0x4 */
    C_CTRL1copy &= 0xFCFF;
    C_CTRL1copy |= 0x0400;
    CAN_REG(CANbaseAddress, C_CTRL1) = C_CTRL1copy;

    /* while OPMODE != 4 */
    while((CAN_REG(CANbaseAddress, C_CTRL1) & 0x00E0) != 0x0080);
}
Example #4
0
void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule){
    uint16_t C_CTRL1copy = CAN_REG(CANmodule->CANbaseAddress, C_CTRL1);

    /* set REQOP = 0x0 */
    C_CTRL1copy &= 0xF8FF;
    CAN_REG(CANmodule->CANbaseAddress, C_CTRL1) = C_CTRL1copy;

    /* while OPMODE != 0 */
    while((CAN_REG(CANmodule->CANbaseAddress, C_CTRL1) & 0x00E0) != 0x0000);

    CANmodule->CANnormal = true;
}
Example #5
0
CO_ReturnError_t CO_CANrxBufferInit(
        CO_CANmodule_t         *CANmodule,
        uint16_t                index,
        uint16_t                ident,
        uint16_t                mask,
        bool_t                  rtr,
        void                   *object,
        void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message))
{
    CO_ReturnError_t ret = CO_ERROR_NO;

    if((CANmodule!=NULL) && (object!=NULL) && (pFunct!=NULL) && (index < CANmodule->rxSize)){
        /* buffer, which will be configured */
        CO_CANrx_t *buffer = &CANmodule->rxArray[index];
        uint16_t RXF, RXM;
        uint16_t addr = CANmodule->CANbaseAddress;

        /* Configure object variables */
        buffer->object = object;
        buffer->pFunct = pFunct;


        /* CAN identifier and CAN mask, bit aligned with CAN module registers (in DMA RAM) */
        RXF = (ident & 0x07FF) << 2;
        if(rtr){
            RXF |= 0x02;
        }
        RXM = (mask & 0x07FF) << 2;
        RXM |= 0x02;

        /* configure filter and mask */
        if(RXF != buffer->ident || RXM != buffer->mask){
            volatile uint16_t C_CTRL1old = CAN_REG(addr, C_CTRL1);
            CAN_REG(addr, C_CTRL1) = C_CTRL1old | 0x0001;     /* WIN = 1 - use filter registers */
            buffer->ident = RXF;
            buffer->mask = RXM;

            /* Set CAN hardware module filter and mask. */
            if(CANmodule->useCANrxFilters){
                volatile uint16_t *pRXF;
                volatile uint16_t *pRXM0, *pRXM1, *pRXM2;
                uint16_t selectMask;

                /* align RXF and RXM with C_RXF_SID and C_RXM_SID registers */
                RXF &= 0xFFFD; RXF <<= 3;
                RXM &= 0xFFFD; RXM <<= 3; RXM |= 0x0008;

                /* write to filter */
                pRXF = &CAN_REG(addr, C_RXF0SID); /* pointer to first filter register */
                pRXF += index * 2;   /* now points to C_RXFiSID (i == index) */
                *pRXF = RXF;         /* write value to filter */

                /* configure mask (There are three masks, each of them can be asigned to any filter. */
                /*                 First mask has always the value 0xFFE8 - all 11 bits must match). */
                pRXM0 = &CAN_REG(addr, C_RXM0SID);
                pRXM1 = &CAN_REG(addr, C_RXM1SID);
                pRXM2 = &CAN_REG(addr, C_RXM2SID);
                if(RXM == 0xFFE8){
                    selectMask = 0;
                }
                else if(RXM == *pRXM1 || *pRXM1 == 0xFFE8){
                    /* RXM is equal to mask 1 or mask 1 was not yet configured. */
                    *pRXM1 = RXM;
                    selectMask = 1;
                }
                else if(RXM == *pRXM2 || *pRXM2 == 0xFFE8){
                    /* RXM is equal to mask 2 or mask 2 was not yet configured. */
                    *pRXM2 = RXM;
                    selectMask = 2;
                }
                else{
                    /* not enough masks */
                    ret = CO_ERROR_OUT_OF_MEMORY;
                    selectMask = 0;
                }
                if(ret == CO_ERROR_NO){
                    /* now write to appropriate mask select register */
                    if(index<8){
                        uint16_t clearMask = ~(0x0003 << (index << 1));
                        selectMask = selectMask << (index << 1);
                        CAN_REG(addr, C_FMSKSEL1) =
                            (CAN_REG(addr, C_FMSKSEL1) & clearMask) | selectMask;
                    }
                    else{
                        uint16_t clearMask = ~(0x0003 << ((index-8) << 1));
                        selectMask = selectMask << ((index-8) << 1);
                        CAN_REG(addr, C_FMSKSEL2) =
                            (CAN_REG(addr, C_FMSKSEL2) & clearMask) | selectMask;
                    }
                }
            }
            CAN_REG(addr, C_CTRL1) = C_CTRL1old;
        }
    }
    else{
        ret = CO_ERROR_ILLEGAL_ARGUMENT;
    }

    return ret;
}
Example #6
0
CO_ReturnError_t CO_CANmodule_init(
        CO_CANmodule_t         *CANmodule,
        uint16_t                CANbaseAddress,
        CO_CANrx_t              rxArray[],
        uint16_t                rxSize,
        CO_CANtx_t              txArray[],
        uint16_t                txSize,
        uint16_t                CANbitRate)
{
    uint16_t i;
    volatile uint16_t *pRXF;

    uint16_t DMArxBaseAddress;
    uint16_t DMAtxBaseAddress;
    __eds__ CO_CANrxMsg_t *CANmsgBuff;
    uint8_t CANmsgBuffSize;
    uint16_t CANmsgBuffDMAoffset;
#if defined(__HAS_EDS__)
    uint16_t CANmsgBuffDMApage;
#endif

    /* verify arguments */
    if(CANmodule==NULL || rxArray==NULL || txArray==NULL){
        return CO_ERROR_ILLEGAL_ARGUMENT;
    }

    /* Get global addresses for CAN module 1 or 2. */
    if(CANbaseAddress == ADDR_CAN1) {
        DMArxBaseAddress = CO_CAN1_DMA0;
        DMAtxBaseAddress = CO_CAN1_DMA1;
        CANmsgBuff = &CO_CAN1msg[0];
        CANmsgBuffSize = CO_CAN1msgBuffSize;
        CANmsgBuffDMAoffset = __builtin_dmaoffset(&CO_CAN1msg[0]);
    #if defined(__HAS_EDS__)
        CANmsgBuffDMApage = __builtin_dmapage(&CO_CAN1msg[0]);
    #endif
    }
#if CO_CAN2msgBuffSize > 0
    else if(CANbaseAddress == ADDR_CAN2) {
        DMArxBaseAddress = CO_CAN2_DMA0;
        DMAtxBaseAddress = CO_CAN2_DMA1;
        CANmsgBuff = &CO_CAN2msg[0];
        CANmsgBuffSize = CO_CAN2msgBuffSize;
        CANmsgBuffDMAoffset = __builtin_dmaoffset(&CO_CAN2msg[0]);
    #if defined(__HAS_EDS__)
        CANmsgBuffDMApage = __builtin_dmapage(&CO_CAN2msg[0]);
    #endif
    }
#endif
    else {
        return CO_ERROR_ILLEGAL_ARGUMENT;
    }

    /* Configure object variables */
    CANmodule->CANbaseAddress = CANbaseAddress;
    CANmodule->CANmsgBuff = CANmsgBuff;
    CANmodule->rxArray = rxArray;
    CANmodule->rxSize = rxSize;
    CANmodule->txArray = txArray;
    CANmodule->txSize = txSize;
    CANmodule->useCANrxFilters = (rxSize <= 16U) ? true : false;
    CANmodule->bufferInhibitFlag = false;
    CANmodule->firstCANtxMessage = true;
    CANmodule->CANtxCount = 0U;
    CANmodule->errOld = 0U;
    CANmodule->em = NULL;

    for(i=0U; i<rxSize; i++){
        rxArray[i].ident = 0U;
        rxArray[i].pFunct = NULL;
    }
    for(i=0U; i<txSize; i++){
        txArray[i].bufferFull = false;
    }


    /* Configure control registers */
    CAN_REG(CANbaseAddress, C_CTRL1) = 0x0400;
    CAN_REG(CANbaseAddress, C_CTRL2) = 0x0000;


    /* Configure CAN timing */
    switch(CANbitRate){
        case 10:   i=0; break;
        case 20:   i=1; break;
        case 50:   i=2; break;
        default:
        case 125:  i=3; break;
        case 250:  i=4; break;
        case 500:  i=5; break;
        case 800:  i=6; break;
        case 1000: i=7; break;
    }

    if(CO_CANbitRateData[i].scale == 2)
        CAN_REG(CANbaseAddress, C_CTRL1) |= 0x0800;

    CAN_REG(CANbaseAddress, C_CFG1) = (CO_CANbitRateData[i].SJW - 1) << 6 |
                                        (CO_CANbitRateData[i].BRP - 1);

    CAN_REG(CANbaseAddress, C_CFG2) = ((uint16_t)(CO_CANbitRateData[i].phSeg2 - 1)) << 8 |
                                        0x0080 |
                                        (CO_CANbitRateData[i].phSeg1 - 1) << 3 |
                                        (CO_CANbitRateData[i].PROP - 1);


    /* setup RX and TX control registers */
    CAN_REG(CANbaseAddress, C_CTRL1) &= 0xFFFE;     /* WIN = 0 - use buffer registers */
    CAN_REG(CANbaseAddress, C_RXFUL1) = 0x0000;
    CAN_REG(CANbaseAddress, C_RXFUL2) = 0x0000;
    CAN_REG(CANbaseAddress, C_RXOVF1) = 0x0000;
    CAN_REG(CANbaseAddress, C_RXOVF2) = 0x0000;
    CAN_REG(CANbaseAddress, C_TR01CON) = 0x0080;    /* use one buffer for transmission */
    CAN_REG(CANbaseAddress, C_TR23CON) = 0x0000;
    CAN_REG(CANbaseAddress, C_TR45CON) = 0x0000;
    CAN_REG(CANbaseAddress, C_TR67CON) = 0x0000;


    /* CAN module hardware filters */
    CAN_REG(CANbaseAddress, C_CTRL1) |= 0x0001;     /* WIN = 1 - use filter registers */
    CAN_REG(CANbaseAddress, C_FEN1) = 0xFFFF;       /* enable all 16 filters */
    CAN_REG(CANbaseAddress, C_FMSKSEL1) = 0x0000;   /* all filters are using mask 0 */
    CAN_REG(CANbaseAddress, C_FMSKSEL2) = 0x0000;
    CAN_REG(CANbaseAddress, C_BUFPNT1) = 0xFFFF;    /* use FIFO for all filters */
    CAN_REG(CANbaseAddress, C_BUFPNT2) = 0xFFFF;
    CAN_REG(CANbaseAddress, C_BUFPNT3) = 0xFFFF;
    CAN_REG(CANbaseAddress, C_BUFPNT4) = 0xFFFF;
    /* set all filters to 0 */
    pRXF = &CAN_REG(CANbaseAddress, C_RXF0SID);
    for(i=0; i<16; i++){
        *pRXF = 0x0000;
        pRXF += 2;
    }
    if(CANmodule->useCANrxFilters){
        /* CAN module filters are used, they will be configured with */
        /* CO_CANrxBufferInit() functions, called by separate CANopen */
        /* init functions. */
        /* All mask bits are 1, so received message must match filter */
        CAN_REG(CANbaseAddress, C_RXM0SID) = 0xFFE8;
        CAN_REG(CANbaseAddress, C_RXM1SID) = 0xFFE8;
        CAN_REG(CANbaseAddress, C_RXM2SID) = 0xFFE8;
    }
    else{
        /* CAN module filters are not used, all messages with standard 11-bit */
        /* identifier will be received */
        /* Set masks so, that all messages with standard identifier are accepted */
        CAN_REG(CANbaseAddress, C_RXM0SID) = 0x0008;
        CAN_REG(CANbaseAddress, C_RXM1SID) = 0x0008;
        CAN_REG(CANbaseAddress, C_RXM2SID) = 0x0008;
    }

    /* WIN = 0 - use buffer registers for default */
    CAN_REG(CANbaseAddress, C_CTRL1) &= 0xFFFE;


    /* Configure DMA controller */
    /* Set size of buffer in DMA RAM (FIFO Area Starts with Tx/Rx buffer TRB1 (FSA = 1)) */
    /* Use maximum 16 buffers, because we have 16-bit system. */
    if (CANmsgBuffSize >= 16) {
        CAN_REG(CANbaseAddress, C_FCTRL) = 0x8001;
        CANmodule->CANmsgBuffSize = 16;
    }
    else if(CANmsgBuffSize >= 12) {
        CAN_REG(CANbaseAddress, C_FCTRL) = 0x6001;
        CANmodule->CANmsgBuffSize = 12;
    }
    else if(CANmsgBuffSize >=  8) {
        CAN_REG(CANbaseAddress, C_FCTRL) = 0x4001;
        CANmodule->CANmsgBuffSize = 8;
    }
    else if(CANmsgBuffSize >=  6) {
        CAN_REG(CANbaseAddress, C_FCTRL) = 0x2001;
        CANmodule->CANmsgBuffSize = 6;
    }
    else if(CANmsgBuffSize >=  4) {
        CAN_REG(CANbaseAddress, C_FCTRL) = 0x0001;
        CANmodule->CANmsgBuffSize = 4;
    }
    else {
        return CO_ERROR_ILLEGAL_ARGUMENT;
    }

    /* DMA chanel initialization for ECAN reception */
    DMA_REG(DMArxBaseAddress, DMA_CON) = 0x0020;
    DMA_REG(DMArxBaseAddress, DMA_PAD) = (volatile uint16_t) &CAN_REG(CANbaseAddress, C_RXD);
    DMA_REG(DMArxBaseAddress, DMA_CNT) = 7;
    DMA_REG(DMArxBaseAddress, DMA_REQ) = (CANbaseAddress==ADDR_CAN1) ? 34 : 55;

#ifndef __HAS_EDS__
    DMA_REG(DMArxBaseAddress, DMA_STA) = CANmsgBuffDMAoffset;
#else
    DMA_REG(DMArxBaseAddress, DMA_STAL) = CANmsgBuffDMAoffset;
    DMA_REG(DMArxBaseAddress, DMA_STAH) = CANmsgBuffDMApage;
#endif

    DMA_REG(DMArxBaseAddress, DMA_CON) = 0x8020;

    /* DMA chanel initialization for ECAN transmission */
    DMA_REG(DMAtxBaseAddress, DMA_CON) = 0x2020;
    DMA_REG(DMAtxBaseAddress, DMA_PAD) = (volatile uint16_t) &CAN_REG(CANbaseAddress, C_TXD);
    DMA_REG(DMAtxBaseAddress, DMA_CNT) = 7;
    DMA_REG(DMAtxBaseAddress, DMA_REQ) = (CANbaseAddress==ADDR_CAN1) ? 70 : 71;

#ifndef __HAS_EDS__
    DMA_REG(DMAtxBaseAddress, DMA_STA) = CANmsgBuffDMAoffset;
#else
    DMA_REG(DMAtxBaseAddress, DMA_STAL) = CANmsgBuffDMAoffset;
    DMA_REG(DMAtxBaseAddress, DMA_STAH) = CANmsgBuffDMApage;
#endif

    DMA_REG(DMAtxBaseAddress, DMA_CON) = 0xA020;


    /* CAN interrupt registers */
    /* clear interrupt flags */
    CAN_REG(CANbaseAddress, C_INTF) = 0x0000;
    /* enable receive and transmit interrupt */
    CAN_REG(CANbaseAddress, C_INTE) = 0x0003;
    /* CAN interrupt (combined) must be configured by application */

    return CO_ERROR_NO;
}
Example #7
0
    CO_ReturnError_t err = CO_ERROR_NO;
    uint16_t addr = CANmodule->CANbaseAddress;
    volatile uint16_t C_CTRL1old, C_TR01CONcopy;

    /* Verify overflow */
    if(buffer->bufferFull){
        if(!CANmodule->firstCANtxMessage){
            /* don't set error, if bootup message is still on buffers */
            CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, (buffer->ident >> 2) & 0x7FF);
        }
        err = CO_ERROR_TX_OVERFLOW;
    }

    CO_LOCK_CAN_SEND();
    /* read C_TR01CON */
    C_CTRL1old = CAN_REG(addr, C_CTRL1);
    CAN_REG(addr, C_CTRL1) = C_CTRL1old & 0xFFFE;     /* WIN = 0 - use buffer registers */
    C_TR01CONcopy = CAN_REG(addr, C_TR01CON);
    CAN_REG(addr, C_CTRL1) = C_CTRL1old;

    /* if CAN TX buffer is free, copy message to it */
    if((C_TR01CONcopy & 0x8) == 0 && CANmodule->CANtxCount == 0){
        CANmodule->bufferInhibitFlag = buffer->syncFlag;
        CO_CANsendToModule(addr, CANmodule->CANmsgBuff, buffer);
    }
    /* if no buffer is free, message will be sent by interrupt */
    else{
        buffer->bufferFull = true;
        CANmodule->CANtxCount++;
    }
    CO_UNLOCK_CAN_SEND();
Example #8
0
int can_tx_now(CAN_CHANNEL chan){
  volatile unsigned long* base = can_tx_chan_cfgs[chan].base_addr;
  CAN_FRAME frame;
  int sent = 0;
  if (CAN_REG(base, CAN_SR) & (1<<2)) // buffer 1 is available
  {   
    can_ring_pop(can_tx_chan_cfgs[chan].ring, &frame);
    CAN_REG(base, CAN_TFI1) = 1<<19;  //Data length 8, FF = 0, RTR = 0, PRIO = 0
    CAN_REG(base, CAN_TID1) = frame.addr;   //get CAN_ID
    CAN_REG(base, CAN_TDA1) = frame.payload.w.w1;   //load first data word
    CAN_REG(base, CAN_TDB1) = frame.payload.w.w2;   //load second data word	
    CAN_REG(base, CAN_CMR) = (1<<0) | (1<<5);     // Select buffer 1, request transmission  
    can_add_frame_count(chan);
    sent++;
  }
  else if (CAN_REG(base, CAN_SR) & (1<<10)) // buffer 2 is available
  {
    can_ring_pop(can_tx_chan_cfgs[chan].ring, &frame);
    CAN_REG(base, CAN_TFI2) = 1<<19;  //Data length 8, FF = 0, RTR = 0, PRIO = 0
    CAN_REG(base, CAN_TID2) = frame.addr;   //get CAN_ID
    CAN_REG(base, CAN_TDA2) = frame.payload.w.w1;   //load first data word
    CAN_REG(base, CAN_TDB2) = frame.payload.w.w2;   //load second data word	
    CAN_REG(base, CAN_CMR) = (1<<0) | (1<<6);     // Select buffer 2, request transmission  
    can_add_frame_count(chan);
    sent++;
  }
  return sent;
}