Subversion Repositories HomeAutomation

Rev

Rev 678 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Controller Area Network (CAN) Demo-Application
  4.  * Atmel AVR with Microchip MCP2515
  5.  *
  6.  * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany
  7.  * <eversmith@heizung-thomas.de>
  8.  * http://www.siwawi.arubi.uni-kl.de/avr_projects
  9.  *
  10.  *****************************************************************************
  11.  *
  12.  * File    : mcp2515.c
  13.  * Version : 0.9
  14.  *
  15.  * Summary : MCP2515 "low-level" driver
  16.  *
  17.  * Parts of this code are adapted from a MCP2510 sample-application
  18.  * by KVASER AB, http://www.kvaser.com (KVASER-code is marked as free)
  19.  *
  20.  * This code-module is free to use but you have to keep the copyright
  21.  * notice.
  22.  *
  23.  *****************************************************************************/
  24.  
  25. #include <inttypes.h>
  26. //#include <stdio.h>
  27. #include <avr/io.h>
  28. #include <avr/interrupt.h>
  29. #include <drivers/can/mcp2515/mcp2515.h>
  30. #include <drivers/can/mcp2515/mcp2515_defs.h>
  31. #include <drivers/can/mcp2515/mcp2515_bittime.h>
  32.  
  33. #include <vectors.h>
  34.  
  35.  
  36. #define SPI_PORT    PORTB
  37. #define SPI_PIN     PINB
  38. #define SPI_DDR     DDRB
  39.  
  40. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  41.     #define SPI_SCK   PB5  
  42.     #define SPI_MISO  PB4
  43.     #define SPI_MOSI  PB3  
  44. #elif defined(__AVR_ATmega32__) || defined(__AVR_ATmega16__)
  45.     #define SPI_SCK   PB7
  46.     #define SPI_MISO  PB6
  47.     #define SPI_MOSI  PB5  
  48. #else
  49.     #error "SPI pins undefined for this target (see spi.h)"
  50. #endif
  51.  
  52. static void SPI_Init(void);
  53. static uint8_t SPI_ReadWrite(uint8_t data);
  54. static uint8_t SPI_Read(void);
  55.  
  56. #define SPI_DONTCARE (0x00)
  57.  
  58. // init as SPI-Master
  59. static void SPI_Init(void) {
  60.     // SCK, SS!!, MOSI as outputs
  61.     SPI_DDR |= (1<<SPI_SCK) | (1<<SPI_MOSI);
  62.     // MISO as input
  63.     SPI_DDR &= ~(1<<SPI_MISO);
  64.     // INIT interface, Master, set clock rate fck/4
  65.     SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);
  66.     // enable double rate
  67.     SPSR = (1<<SPI2X); // we will now gain fck/2 instead of fck/4
  68. }
  69.  
  70. static uint8_t SPI_ReadWrite(uint8_t data) {
  71.     // set data to send into SPI data register
  72.     SPDR = data;
  73.     // Wait for transmission complete
  74.     while(!(SPSR & (1<<SPIF)));
  75.     // return data read from SPI (if any)
  76.     return SPDR;
  77. }
  78.  
  79. static uint8_t SPI_Read(void) {
  80.     return SPI_ReadWrite(SPI_DONTCARE);
  81. }
  82.  
  83. static Can_Message_t msgbuf;
  84.  
  85. void MCP2515_Reset(void) {
  86.     MCP2515_SELECT();
  87.     SPI_ReadWrite(MCP_RESET);
  88.     MCP2515_UNSELECT();
  89.     // delay at least 128 MCP clock cycles
  90.     volatile int16_t i;
  91.     for (i=0; i<32000; i++) {
  92.         if (i < 0) break;
  93.     }
  94. }
  95.  
  96. uint8_t MCP2515_ReadRegister(const uint8_t address) {
  97.     uint8_t ret;
  98.    
  99.     MCP2515_SELECT();
  100.     SPI_ReadWrite(MCP_READ);
  101.     SPI_ReadWrite(address);
  102.     ret = SPI_Read();
  103.     MCP2515_UNSELECT();
  104.    
  105.     return ret;
  106. }
  107.  
  108. /*
  109. void MCP2515_ReadRXBuf(const uint8_t buf, uint8_t* data) {
  110.     uint8_t i;
  111.    
  112.     MCP2515_SELECT();
  113.     SPI_ReadWrite(MCP_READ_RX0 + ((buf & 0x1) << 2));
  114.     // mcp2515 has auto-increment of address-pointer
  115.     for (i=0; i<13; i++) {
  116.         data[i] = SPI_Read();
  117.     }
  118.     MCP2515_UNSELECT();
  119. }*/
  120.  
  121. void MCP2515_SetRegister(const uint8_t address, const uint8_t value) {
  122.     MCP2515_SELECT();
  123.     SPI_ReadWrite(MCP_WRITE);
  124.     SPI_ReadWrite(address);
  125.     SPI_ReadWrite(value);
  126.     MCP2515_UNSELECT();
  127. }
  128.  
  129. /*
  130. void MCP2515_SetRegisterS(const uint8_t address, const uint8_t values[], const uint8_t n) {
  131.     uint8_t i;
  132.    
  133.     MCP2515_SELECT();
  134.     SPI_ReadWrite(MCP_WRITE);
  135.     SPI_ReadWrite(address);
  136.     // mcp2515 has auto-increment of address-pointer
  137.     for (i=0; i<n; i++) {
  138.         SPI_ReadWrite(values[i]);
  139.     }
  140.     MCP2515_UNSELECT();
  141. }*/
  142.  
  143. void MCP2515_ModifyRegister(const uint8_t address, const uint8_t mask, const uint8_t data) {
  144.     MCP2515_SELECT();
  145.     SPI_ReadWrite(MCP_BITMOD);
  146.     SPI_ReadWrite(address);
  147.     SPI_ReadWrite(mask);
  148.     SPI_ReadWrite(data);
  149.     MCP2515_UNSELECT();
  150. }
  151.  
  152. uint8_t MCP2515_ReadStatus(void) {
  153.     uint8_t i;
  154.    
  155.     MCP2515_SELECT();
  156.     SPI_ReadWrite(MCP_READ_STATUS);
  157.     i = SPI_Read();
  158.     MCP2515_UNSELECT();
  159.    
  160.     return i;
  161. }
  162.    
  163. /*uint8_t MCP2515_ReadStatus(void) {
  164.     return MCP2515_ReadXXStatus_Helper(MCP_READ_STATUS);
  165. }*/
  166.  
  167. /*uint8_t MCP2515_RxStatus(void) {
  168.     return MCP2515_ReadXXStatus_Helper(MCP_RX_STATUS);
  169. }*/
  170.  
  171. uint8_t MCP2515_SetCanCtrl(const uint8_t newmask, const uint8_t newmode) {
  172.     uint8_t i;
  173.     MCP2515_ModifyRegister(MCP_CANCTRL, newmask, newmode);
  174.     // verify as advised in datasheet
  175.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  176.     i &= newmask;
  177.     if ( i == newmode ) {
  178.         return MCP2515_OK;
  179.     }
  180.     else {
  181.         return MCP2515_FAIL;
  182.     }
  183. }
  184.  
  185. /*uint8_t MCP2515_SetClkout(const uint8_t newmode) {
  186.     uint8_t i;
  187.     MCP2515_ModifyRegister(MCP_CANCTRL, CLK_MASK, newmode);
  188.     // verify, perhaps not needed?
  189.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  190.     i &= CLK_MASK;
  191.     if ( i == newmode ) {
  192.         return MCP2515_OK;
  193.     }
  194.     else {
  195.         return MCP2515_FAIL;
  196.     }
  197. }*/
  198.  
  199. inline void MCP2515_ConfigRate(void) {
  200.     MCP2515_SetRegister(MCP_CNF1, MCP_BITRATE_CFG1);
  201.     MCP2515_SetRegister(MCP_CNF2, MCP_BITRATE_CFG2);
  202.     MCP2515_SetRegister(MCP_CNF3, MCP_BITRATE_CFG3);
  203. }
  204.  
  205. /**
  206.  * Reads a CAN message from the specified buffer base address in the MCP2515. The message
  207.  * is stored in the following format:
  208.  *
  209.  *      BASE+0:
  210.  *      | SID10 | SID9  | SID8  | SID7  | SID6  | SID5  | SID4  | SID3  |
  211.  *     
  212.  *      BASE+1:
  213.  *      | SID2  | SID1  | SID0  | SRR   | IDE   |       | EID17 | EID16 |
  214.  *     
  215.  *      BASE+2:
  216.  *      | EID15 | EID14 | EID13 | EID12 | EID11 | EID10 | EID9  | EID8  |
  217.  *     
  218.  *      BASE+3:
  219.  *      | EID7  | EID6  | EID5  | EID4  | EID3  | EID2  | EID1  | EID0  |
  220.  *     
  221.  *      BASE+4:
  222.  *      |       |  RTR  |  RB1  |  RB0  | DLC3  | DLC2  | DLC1  | DCL0  |
  223.  *     
  224.  *      BASE+5 - BASE+12:
  225.  *      DATA0 - DATA7
  226.  *
  227.  * @param buffer_sidh_addr
  228.  *      Base address to the RX buffer.
  229.  *
  230.  * @param msg
  231.  *      Pointer to the message buffer into which the data should be copied.
  232.  *
  233.  */
  234. void MCP2515_ReadCanMsg(const uint8_t buffer, Can_Message_t* msg) {
  235.     uint8_t id[4];
  236.     uint8_t i;
  237.  
  238.     MCP2515_SELECT();
  239.     SPI_ReadWrite(MCP_READ_RX0 + ((buffer & 0x1) << 2));
  240.     // mcp2515 has auto-increment of address-pointer
  241.    
  242.     // read ID
  243.     for (i=0; i<4; i++) {
  244.         id[i] = SPI_Read();
  245.     }
  246.    
  247.     // extract SID10-SID0
  248.     uint16_t stdid = (((uint16_t)(id[0])) << 3) | (((uint16_t)(id[1] & 0xE0)) >> 5);
  249.    
  250.     if (id[1] & MCP_TXB_EXIDE_M) {
  251.         // extended message
  252.         msg->ExtendedFlag = 1;
  253.         // SID10-SID0 are still most significant, so shift them up
  254.         // and make room for 18 extended least significant EID-bits
  255.         msg->Id = ((uint32_t)stdid) << 18;
  256.         // exctract EID17-EID16
  257.         msg->Id |= (((uint32_t)(id[1] & 0x03))<<16);
  258.         // extract EID15-EID8
  259.         msg->Id |= (((uint32_t)id[2])<<8);
  260.         // extract EID7-EID0
  261.         msg->Id |= ((uint32_t)id[3]);
  262.     }
  263.     else {
  264.         // standard message
  265.         msg->ExtendedFlag = 0;
  266.         msg->Id = stdid;
  267.     }
  268.    
  269.     // extract DLC
  270.     uint8_t rtrdlc = SPI_Read();
  271.     msg->DataLength = rtrdlc & 0x0F;
  272.     if (msg->DataLength > 8) msg->DataLength = 8;   // saturate DLC to guarantee 0-8 range
  273.    
  274.     // check RTR flag
  275.     msg->RemoteFlag = (rtrdlc & 0x40) > 0;
  276.    
  277.     // read data
  278.     for (i=0; i<msg->DataLength; i++) {
  279.         msg->Data.bytes[i] = SPI_Read();
  280.     }
  281.     MCP2515_UNSELECT();
  282. }
  283.  
  284.  
  285. void MCP2515_SPIWriteCanId(const uint8_t ext, const uint32_t can_id) {
  286.     uint16_t canid = can_id & 0xFFFF;
  287.     uint8_t tbufdata[4];
  288.     uint8_t i;
  289.    
  290.     if (ext) {
  291.         tbufdata[3] = canid & 0xFF;
  292.         tbufdata[2] = canid >> 8;
  293.         canid = can_id >> 16;
  294.         tbufdata[1] = canid & 0x03;
  295.         tbufdata[1] += (canid & 0x1C ) << 3;
  296.         tbufdata[1] |= MCP_TXB_EXIDE_M;
  297.         tbufdata[0] = canid >> 5;
  298.     }
  299.     else {
  300.         tbufdata[0] = canid >> 3;
  301.         tbufdata[1] = (canid & 0x07 ) << 5;
  302.         tbufdata[2] = 0;
  303.         tbufdata[3] = 0;
  304.     }
  305.     for (i=0; i<4; i++) {
  306.         SPI_ReadWrite(tbufdata[i]);
  307.     }
  308. }
  309.  
  310.  
  311. void MCP2515_WriteCanId(const uint8_t mcp_addr, const uint8_t ext, const uint32_t can_id) {
  312.     MCP2515_SELECT();
  313.     SPI_ReadWrite(MCP_WRITE);
  314.     SPI_ReadWrite(mcp_addr);
  315.     MCP2515_SPIWriteCanId(ext, can_id);
  316.     MCP2515_UNSELECT();
  317. }
  318.  
  319. // Buffer can be 0, 1 or 2
  320. void MCP2515_WriteCanMsg( const uint8_t buffer, const Can_Message_t* msg) {
  321.     uint8_t rtrdlc = msg->DataLength;
  322.     uint8_t i;
  323.    
  324.     MCP_INT_DISABLE();
  325.     MCP2515_SELECT();
  326.     SPI_ReadWrite(MCP_LOAD_TX0 | (buffer << 1));
  327.     MCP2515_SPIWriteCanId(msg->ExtendedFlag, msg->Id);
  328.     if (msg->RemoteFlag == 1)  rtrdlc |= MCP_RTR_MASK;  // if RTR set bit in byte
  329.     SPI_ReadWrite(rtrdlc);
  330.     //MCP2515_UNSELECT();
  331.     //MCP_INT_ENABLE();
  332.  
  333.     //MCP_INT_DISABLE();
  334.     //MCP2515_SELECT();
  335.     for (i=0; i<msg->DataLength; i++) {
  336.         SPI_ReadWrite(msg->Data.bytes[i]);
  337.     }
  338.     MCP2515_UNSELECT();
  339.     MCP_INT_ENABLE();
  340. }
  341.  
  342.  
  343. // Start the transmission from one of the tx buffers.
  344. //
  345. // Buffer can be 0, 1 or 2
  346. void MCP2515_StartTransmit(const uint8_t buffer) {
  347.     MCP_INT_DISABLE();
  348.     MCP2515_SELECT();
  349.     SPI_ReadWrite(MCP_RTS_TX | (1 << buffer));
  350.     MCP2515_UNSELECT();
  351.     MCP_INT_ENABLE();
  352. }
  353.  
  354. uint8_t MCP2515_GetNextFreeTXBuf(void) {
  355.     uint8_t stat;
  356.    
  357.     // check all 3 TX-Buffers
  358.     MCP_INT_DISABLE();
  359.     stat = MCP2515_ReadStatus();
  360.     MCP_INT_ENABLE();
  361.     if (!(stat & MCP_STAT_TX0REQ)) return 0;
  362.     if (!(stat & MCP_STAT_TX1REQ)) return 1;
  363.     if (!(stat & MCP_STAT_TX2REQ)) return 2;
  364.     return MCP_ALLTXBUSY;
  365. }
  366.  
  367. void MCP2515_InitCanBuffers(void) {
  368.     uint8_t i;
  369.    
  370.     // TODO: check why this is needed to receive extended
  371.     //   and standard frames
  372.     // Mark all filter bits as don't care:
  373.     MCP2515_WriteCanId(MCP_RXM0SIDH, 0, 0);
  374.     MCP2515_WriteCanId(MCP_RXM1SIDH, 0, 0);
  375.     // Anyway, set all filters to 0:
  376.     MCP2515_WriteCanId(MCP_RXF0SIDH, 1, 0); // RXB0: extended
  377.     MCP2515_WriteCanId(MCP_RXF1SIDH, 0, 0); //       AND standard
  378.     MCP2515_WriteCanId(MCP_RXF2SIDH, 1, 0); // RXB1: extended
  379.     MCP2515_WriteCanId(MCP_RXF3SIDH, 0, 0); //       AND standard
  380.     MCP2515_WriteCanId(MCP_RXF4SIDH, 0, 0);
  381.     MCP2515_WriteCanId(MCP_RXF5SIDH, 0, 0);
  382.    
  383.     // Clear, deactivate the three transmit buffers
  384.     // TXBnCTRL -> TXBnD7
  385.     for (i = 0; i < 14; i++) { // in-buffer loop
  386.         MCP2515_SetRegister(MCP_TXB0CTRL + i, 0);
  387.         MCP2515_SetRegister(MCP_TXB1CTRL + i, 0);
  388.         MCP2515_SetRegister(MCP_TXB2CTRL + i, 0);
  389.     }
  390.    
  391.     // and clear, deactivate the two receive buffers.
  392.     MCP2515_SetRegister(MCP_RXB0CTRL, 0);
  393.     MCP2515_SetRegister(MCP_RXB1CTRL, 0);
  394. }
  395.  
  396.  
  397. void MCP2515_InitRXInterrupts(void) {
  398.     MCP2515_SetRegister(MCP_CANINTF, 0);
  399.     MCP2515_SetRegister(MCP_CANINTE, MCP_RX_INT);
  400.     MCP_INT_ENABLE();
  401. }
  402.  
  403. // ---
  404.  
  405. uint8_t MCP2515_Init(void) {
  406.     uint8_t res;
  407.    
  408. #if MCP_CS_BIT != SS
  409.     /* If slave select is not set as output it might change SPI hw to slave
  410.      * See ch 18.3.2 (18.3 SS Pin Functionality) in ATmega48/88/168-datasheet */
  411.     DDRSS |= (1<<SS);
  412. #endif
  413.    
  414.     SPI_Init();     // init SPI-Interface (as "Master")
  415.    
  416.     MCP2515_UNSELECT();
  417.     MCP_CS_DDR |= ( 1 << MCP_CS_BIT );
  418.    
  419.     MCP2515_Reset();
  420.    
  421.     res = MCP2515_SetCanCtrl(MODE_MASK, MODE_CONFIG);
  422.    
  423.     if (res == MCP2515_FAIL) return res;  /* function exit on error */
  424.  
  425.     /* Set prescaler for clock output */
  426.     res = MCP2515_SetCanCtrl(CLK_MASK, MCP_PRESCALER);
  427.    
  428.     if (res == MCP2515_FAIL) return res;  /* function exit on error */
  429.    
  430.     MCP2515_ConfigRate();
  431.    
  432.     MCP2515_InitCanBuffers();
  433.  
  434. #if (DEBUG_RXANY==1)
  435.     #warning DEBUG_RXANY is defined! Bypassing filter.
  436.         // enable both receive-buffers to receive any message
  437.         // and enable rollover
  438.         MCP2515_ModifyRegister(
  439.                 MCP_RXB0CTRL,
  440.                 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
  441.                 MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
  442.         MCP2515_ModifyRegister(
  443.                 MCP_RXB1CTRL,
  444.                 MCP_RXB_RX_MASK,
  445.                 MCP_RXB_RX_ANY);
  446. #else
  447.         // enable both receive-buffers to receive messages
  448.         // with std. and ext. identifiers
  449.         // and enable rollover
  450.         MCP2515_ModifyRegister(
  451.                 MCP_RXB0CTRL,
  452.                 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
  453.                 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
  454.         MCP2515_ModifyRegister(
  455.                 MCP_RXB1CTRL,
  456.                 MCP_RXB_RX_MASK,
  457.                 MCP_RXB_RX_STDEXT);
  458. #endif
  459.  
  460.     MCP2515_InitRXInterrupts();
  461.    
  462.     return res;
  463. }
  464.  
  465. Can_Return_t Can_Receive(Can_Message_t *msg);
  466.  
  467. ISR(MCP_INT_VECTOR) {
  468.     // Get first available message from controller and pass it to
  469.     // application handler. If both RX buffers contain messages
  470.     // we will get another interrupt as soon as this one returns.
  471.     if (Can_Receive(&msgbuf) == CAN_OK) {
  472.         // Callbacks are run with global interrupts disabled but
  473.         // with controller flag cleared so another msg can be
  474.         // received while this one is processed.
  475.         Can_Process(&msgbuf);
  476.     }
  477. }
  478.  
  479. /*-----------------------------------------------------------------------------
  480.  * Public Functions
  481.  *---------------------------------------------------------------------------*/
  482.  
  483. /**
  484.  * Initializes the CAN interface. Edit can_cfg.h to choose bitrate.
  485.  *
  486.  * @return
  487.  *      CAN_OK if initialization was successful.
  488.  *      CAN_INIT_FAIL_SET_BITRATE if bitrate could not be set correctly.
  489.  *      CAN_INIT_FAIL_SET_MODE if the controller could not be set to normal operation mode.
  490.  *      CAN_INIT_FAIL in case of general error.
  491.  */
  492. Can_Return_t Can_Init(void) {
  493.         /*
  494.          * Initialize MCP2515 device.
  495.          */
  496.         if (MCP2515_Init() != MCP2515_OK) {
  497.             return CAN_FAIL;
  498.         }
  499.         if (MCP2515_SetCanCtrl(MODE_MASK, MODE_NORMAL) != MCP2515_OK) {
  500.             return CAN_FAIL;
  501.         }
  502.         return CAN_OK;
  503.    
  504.     return CAN_FAIL;
  505. }
  506.  
  507. /**
  508.  * Sends a CAN message immediately with the controller hardware. If the CAN
  509.  * controller is busy, the function will return CAN_FAIL.
  510.  *
  511.  * @param msg
  512.  *      Pointer to the CAN message storage buffer.
  513.  *
  514.  * @return
  515.  *      CAN_OK if the message was successfully sent to the controller.
  516.  *      CAN_FAIL if the controller is busy.
  517.  */
  518. Can_Return_t Can_Send(Can_Message_t *msg) {
  519.         /*
  520.          * Send with MCP2515 device.
  521.          */
  522.         uint8_t txbuf_n;
  523.         txbuf_n = MCP2515_GetNextFreeTXBuf();
  524.         if (txbuf_n == MCP_ALLTXBUSY) {
  525.             // TODO: Maybe we should block until a buffer is available?
  526.             return CAN_FAIL;
  527.         }
  528.         MCP2515_WriteCanMsg(txbuf_n, msg);
  529.         MCP2515_StartTransmit(txbuf_n);
  530.         return CAN_OK;
  531. }
  532.  
  533.  
  534. /**
  535.  * Receives a CAN message from the CAN controller hardware.
  536.  *
  537.  * @param msg
  538.  *      Pointer to the message storage buffer into which the message should be copied.
  539.  *
  540.  * @return
  541.  *      CAN_OK if a received message was successfully copied into the buffer.
  542.  *      CAN_NO_MSG_AVAILABLE if there is no message available in the controller.
  543.  */
  544. Can_Return_t Can_Receive(Can_Message_t *msg) {
  545.     /*
  546.      * Receive from MCP2515 device.
  547.      */
  548.     uint8_t stat;
  549.     static uint8_t buffer = 0;
  550.    
  551.     stat = MCP2515_ReadStatus() & MCP_STAT_RXIF_MASK;
  552.    
  553.     if (stat > 2) {
  554.         // Both buffers contain data, read the one previously not read.
  555.         // (Bit 0 in buffer selects which buffer to read, no need to take modulus 2)
  556.         MCP2515_ReadCanMsg(buffer++, msg);
  557.     } else if (stat > 0) {
  558.         // One of the buffers contain data, read it
  559.         MCP2515_ReadCanMsg(stat-1, msg);
  560.     } else {
  561.         // Nothing available
  562.         return CAN_NO_MSG_AVAILABLE;
  563.     }
  564.     return CAN_OK;
  565. }
  566.