This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI issue with softdevice enabled on nRF52840

Our application uses and external nand flash to store the data samples. The collected data is then be transferred using USB. So we chose usbd_ble_uart example and wrote code over it. We are seeing this weird problem of not detecting NAND flash when nRF52840 is erased and programmed. No matter how many times we restart the application, it doesn't work. We've modified spi example in peripherals folder to read ID of the flash. After running this example, the flash starts detecting in our application written over usbd_ble_uart.
Again if we erase the program and program softdevice using nrf gostudio, and then download the application code using segger embedded studio, it is behaves the same. What might be the issue?

Edit: I am using BMD340 (nrf52840 based module). Is this because of any hardware issue?

Best regards,

Vishnu Pradeep

Parents Reply Children
  • Yes , its possible 
    But i also think that NRF_LOG by default is on UART pins(8,6) which are same for your spi slave
    Maybe try interfacing first on the separate pins or not use NRF_LOG

  • I am using NRF_LOG RTT not UART. Even if I disable NRF_LOG the issue exists

  • /** @file mcp_can.c
     *
     * @brief  CAN Bus Protocol to send and receive the data.
     *
     * @par
     * NOTICE: Property of in-Terra Limited www.in-terra.ch .
     */
    
    #include "mcp_can.h"
    #include "logger_hal.h"
    #define TX_RX_MSG_LENGTH 10
    
    // To receive data from the CAN Module after sending the command
    uint8_t dummy_receive[];
    
    // CAN Module Parameter Structure like length of data and extended and Normal
    // ID
    
    mcp_can_t m_mcp_can;
    
    // NOTE: SPI instance index. Both I2C and SPI Can-Not have same instance index (i.e 0).
    //So we are using Instance SPI2 for CAN Communication, also we cannot use 0/spi0 because its already being used by EPAPER
    
    
    #define SPI_CAN_INSTANCE  2
    
    nrf_drv_spi_t SPI_MASTER_0 = NRF_DRV_SPI_INSTANCE (SPI_CAN_INSTANCE);
    static void
    spi_master_init (nrf_drv_spi_t spi_master_instance,
        nrf_drv_spi_evt_handler_t spi_master_event_handler);
    
    
    /**
     * @brief SPI user event handler.
     * @param event
     *
     * @return None
     */
    
    void
    spi_master_0_event_handler (nrf_drv_spi_evt_t const *p_event, void *p_context)
    {
    
    
    
        if (p_event->type == NRF_DRV_SPI_EVENT_DONE)
            {
                can_xfer_done = true;
                
                
            }
    }
    
    /*!
     * @brief     Initilaize the SPI module with pins used and frequency of SPI and
     * Mode of SPI.
     *
     * @param[in] spi_master_instance Instance to be Used.
     * @param[in] nrf_drv_spi_evt_handler_t Event Handler to be used.
     *
     * @return    None.
     */
    
    static void
    spi_master_init (nrf_drv_spi_t spi_master_instance,
        nrf_drv_spi_evt_handler_t spi_master_event_handler)
    {
        uint32_t err_code = NRF_SUCCESS;
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    
        spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;
        spi_config.miso_pin = LOGGER_MISO;
        spi_config.mosi_pin = LOGGER_MOSI;
        spi_config.sck_pin = LOGGER_SCLK;
        spi_config.frequency = NRF_SPI_FREQ_4M;
        spi_config.mode = NRF_DRV_SPI_MODE_0;
        spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
        
        APP_ERROR_CHECK (nrf_drv_spi_init (
            &spi_master_instance, &spi_config, spi_master_0_event_handler, NULL));
    }
    
    /*!
     * @brief     To send command to CAN Module and Receive the data from it.
     *
     * @param[in] spi_master_instance Instance to be Used.
     * @param[in] p_tx_data Pointer to data/command to be transmitted.
     * @param[in] len_tx    Length of the data to be transmitted.
     * @param[in] p_tx_data Pointer to data to store recived data to.
     * @param[in] len_rx    Length of the data to be recived
     *
     * @return    None.
     */
    
    static void
    spi_send_recv (const nrf_drv_spi_t spi_master_hw_instance, uint8_t *p_tx_data,
        uint16_t len_tx, uint8_t *p_rx_data, uint16_t len_rx)
    {
    
        uint8_t *tx_data = p_tx_data;
        uint8_t *rx_data = p_rx_data;
        can_xfer_done = false;
        uint32_t err_code = nrf_drv_spi_transfer (
            &spi_master_hw_instance, tx_data, len_tx, rx_data, len_rx);
    
        while (!can_xfer_done)
            {
    
                __WFE ();
            }
        APP_ERROR_CHECK (err_code);
    }
    
    /*!
     * @brief     To Select the CS pin of CAN Module
     *
     * @param[in] None
     *
     * @return    None.
     */
    
    void
    spi_master_uninit ()
    {
        nrf_drv_spi_uninit (&SPI_MASTER_0);
    }
    /*!
     * @brief     To Select the CS pin of CAN Module
     *
     * @param[in] None
     *
     * @return    None.
     */
    
    void
    mcp_select ()
    {   
        
        nrf_gpio_pin_clear (CS_CAN);
    }
    
    /*!
     * @brief     To UNSELECT/CS PIN HIGH of CAN Module
     *
     * @param[in] None
     *
     * @return    None.
     */
    
    void
    mcp_unselect ()
    {   
       
        nrf_gpio_pin_set (CS_CAN);
    }
    
    /*!
     * @brief     To send reset command so that chip can be configured
     *
     * @param[in] None
     *
     * @return    None.
     */
    
    void
    mcp_can_reset ()
    {
        // To make initally the CS pin HIGH and then pull LOW.
        mcp_unselect ();
    
        uint8_t reset_cmd[1];
        reset_cmd[0] = MCP_RESET;
    
        mcp_select ();
        spi_send_recv (SPI_MASTER_0, &reset_cmd, 1, &dummy_receive, 1);
        SEGGER_RTT_printf (0, "reset can module\r\n");
        mcp_unselect ();
        nrf_delay_ms (10);
    }
    
    /*!
     * @brief     To read value of register.
     *
     * @param[in] address of register to read from
     *
     * @return    Acknowldgement data from MCP2515.
     */
    
    uint8_t
    mcp2515_readRegister (const uint8_t address)
    {
        uint8_t ret;
        uint8_t read_cmd[3] = { MCP_READ, address, 0x00 };
        uint8_t rx_data[3];
        mcp_select ();
        spi_send_recv (SPI_MASTER_0, &read_cmd, 3, &rx_data, 3);
        ret = rx_data[2];
        mcp_unselect ();
        return ret;
    }
    
    /*!
     * @brief To send command to CAN Module and Receive the data from it.
     *
     * @param[in] address of register to read from
     * @param[in] array to store the data from read registers
     * @param[in] variable to run the for loop and number of values to be stored in
     * array.
     * @return None
     */
    
    void
    mcp2515_readRegisterS (
        const uint8_t address, uint8_t values[], const uint8_t n)
    {
        uint8_t i;
        uint8_t read_registers[2] = { MCP_READ, address };
        mcp_select ();
        spi_send_recv (SPI_MASTER_0, &read_registers, 2, &dummy_receive, 2);
    
        for (i = 0; i < n && i < CAN_MAX_CHAR_IN_MESSAGE; i++)
            {
                spi_send_recv (SPI_MASTER_0, 0x00, 1, &values[i], 1);
            }
        mcp_unselect ();
    }
    
    /*!
     * @brief     To write data to a register address
     *
     * @param[in] address of register to write to
     * @param[in] Data to be written/set in register
     * @return    None
     */
    
    void
    mcp2515_setRegister (const uint8_t address, const uint8_t value)
    {
        mcp_select ();
        uint8_t set_registers[3] = { MCP_WRITE, address, value };
        spi_send_recv (SPI_MASTER_0, &set_registers, 3, &dummy_receive, 3);
    
        mcp_unselect ();
    }
    
    /*!
     * @brief     To write data to a register addresses
     *
     * @param[in] Address of register to write to
     * @param[in] Data to be written/set in register
     * @param[in] Variable to write the data to regitser
     * @return    None
     */
    
    void
    mcp2515_setRegisterS (
        const uint8_t address, const uint8_t values[], const uint8_t n)
    {
        uint8_t i;
        mcp_select ();
        uint8_t set_registers[2] = { MCP_WRITE, address };
        spi_send_recv (SPI_MASTER_0, &set_registers, 2, &dummy_receive, 2);
      //  SEGGER_RTT_printf (
       //     0, "Address inside set register function : %x\r\n", address);
    
        for (i = 0; i < n; i++)
            {
                spi_send_recv (SPI_MASTER_0, &values[i], 1, &dummy_receive, 1);
            }
        mcp_unselect ();
    }
    
    /*!
     * @brief     To modify/re-write the register value by sending bit modify
     * instruction in first place
     *
     * @param[in] Address of register to write to
     * @param[in] MODE MASK , AND with result gives us the address we passed
     * @param[in] Data to write to the register
     * @return    None
     */
    
    void
    mcp2515_modifyRegister (
        const uint8_t address, const uint8_t mask, const uint8_t data)
    {
        mcp_select ();
    
        uint8_t modify_reg[4] = { MCP_BITMOD, address, mask, data };
    
        spi_send_recv (SPI_MASTER_0, &modify_reg, 4, &dummy_receive, 4);
    
        mcp_unselect ();
    }
    
    /*!
     * @brief To read the status of different rx and tx bits. Places returned data
     * in array
     *
     * @param[in] None
     * @return Data returned on MISO Line
     */
    
    uint8_t
    mcp2515_readStatus (void)
    {
        uint8_t i;
        mcp_select ();
        uint8_t read_status[2] = { MCP_READ_STATUS, 0x00 };
        uint8_t rx_status[2];
        spi_send_recv (SPI_MASTER_0, &read_status, 2, &rx_status, 2);
    
        mcp_unselect ();
        i = rx_status[1];
    
        return i;
    }
    
    /*!
     * @brief     To Set the mode
     *
     * @param[in] Mode Value in HEX
     * @return    0 : OK! ,1: FAIL
     */
    
    uint8_t
    mcp2515_setCANCTRL_Mode (const uint8_t newmode)
    {
        uint8_t i;
    
        mcp2515_modifyRegister (MCP_CANCTRL, MODE_MASK, newmode);
    
        i = mcp2515_readRegister (MCP_CANCTRL);
    
        i &= MODE_MASK;
    
        if (i == newmode)
            {
                return MCP2515_OK;
            }
    
        return MCP2515_FAIL;
    }
    
    /*!
     * @brief     To Set the Baud Rate
     *
     * @param[in] Required Baud Rate Value
     *
     * @return    0 :OK , 1 : FAILURE
     */
    
    uint8_t
    mcp2515_configRate (const uint8_t canSpeed)
    {
        uint8_t set, cfg1, cfg2, cfg3;
        set = 1;
        switch (canSpeed)
            {
            case (CAN_5KBPS):
                cfg1 = MCP_16MHz_5kBPS_CFG1;
                cfg2 = MCP_16MHz_5kBPS_CFG2;
                cfg3 = MCP_16MHz_5kBPS_CFG3;
                break;
    
            case (CAN_10KBPS):
                cfg1 = MCP_16MHz_10kBPS_CFG1;
                cfg2 = MCP_16MHz_10kBPS_CFG2;
                cfg3 = MCP_16MHz_10kBPS_CFG3;
                break;
    
            case (CAN_20KBPS):
                cfg1 = MCP_16MHz_20kBPS_CFG1;
                cfg2 = MCP_16MHz_20kBPS_CFG2;
                cfg3 = MCP_16MHz_20kBPS_CFG3;
                break;
    
            case (CAN_31K25BPS):
                cfg1 = MCP_16MHz_31k25BPS_CFG1;
                cfg2 = MCP_16MHz_31k25BPS_CFG2;
                cfg3 = MCP_16MHz_31k25BPS_CFG3;
                break;
    
            case (CAN_33KBPS):
                cfg1 = MCP_16MHz_33kBPS_CFG1;
                cfg2 = MCP_16MHz_33kBPS_CFG2;
                cfg3 = MCP_16MHz_33kBPS_CFG3;
                break;
    
            case (CAN_40KBPS):
                cfg1 = MCP_16MHz_40kBPS_CFG1;
                cfg2 = MCP_16MHz_40kBPS_CFG2;
                cfg3 = MCP_16MHz_40kBPS_CFG3;
                break;
    
            case (CAN_50KBPS):
                cfg1 = MCP_16MHz_50kBPS_CFG1;
                cfg2 = MCP_16MHz_50kBPS_CFG2;
                cfg3 = MCP_16MHz_50kBPS_CFG3;
                break;
    
            case (CAN_80KBPS):
                cfg1 = MCP_16MHz_80kBPS_CFG1;
                cfg2 = MCP_16MHz_80kBPS_CFG2;
                cfg3 = MCP_16MHz_80kBPS_CFG3;
                break;
    
            case (CAN_83K3BPS):
                cfg1 = MCP_16MHz_83k3BPS_CFG1;
                cfg2 = MCP_16MHz_83k3BPS_CFG2;
                cfg3 = MCP_16MHz_83k3BPS_CFG3;
                break;
    
            case (CAN_95KBPS):
                cfg1 = MCP_16MHz_95kBPS_CFG1;
                cfg2 = MCP_16MHz_95kBPS_CFG2;
                cfg3 = MCP_16MHz_95kBPS_CFG3;
                break;
    
            case (CAN_100KBPS): /* 100KBPS                  */
                cfg1 = MCP_16MHz_100kBPS_CFG1;
                cfg2 = MCP_16MHz_100kBPS_CFG2;
                cfg3 = MCP_16MHz_100kBPS_CFG3;
                break;
    
            case (CAN_125KBPS):
                cfg1 = MCP_16MHz_125kBPS_CFG1;
                cfg2 = MCP_16MHz_125kBPS_CFG2;
                cfg3 = MCP_16MHz_125kBPS_CFG3;
                break;
    
            case (CAN_200KBPS):
                cfg1 = MCP_16MHz_200kBPS_CFG1;
                cfg2 = MCP_16MHz_200kBPS_CFG2;
                cfg3 = MCP_16MHz_200kBPS_CFG3;
                break;
    
            case (CAN_250KBPS):
                cfg1 = MCP_16MHz_250kBPS_CFG1;
                cfg2 = MCP_16MHz_250kBPS_CFG2;
                cfg3 = MCP_16MHz_250kBPS_CFG3;
                break;
    
            case (CAN_500KBPS):
                cfg1 = MCP_16MHz_500kBPS_CFG1;
                cfg2 = MCP_16MHz_500kBPS_CFG2;
                cfg3 = MCP_16MHz_500kBPS_CFG3;
                break;
    
            case (CAN_1000KBPS):
                cfg1 = MCP_16MHz_1000kBPS_CFG1;
                cfg2 = MCP_16MHz_1000kBPS_CFG2;
                cfg3 = MCP_16MHz_1000kBPS_CFG3;
                break;
    
            default:
                set = 0;
                break;
            }
    
        if (set)
            {
                mcp2515_setRegister (MCP_CNF1, cfg1);
                mcp2515_setRegister (MCP_CNF2, cfg2);
                mcp2515_setRegister (MCP_CNF3, cfg3);
                return MCP2515_OK;
            }
        else
            {
                return MCP2515_FAIL;
            }
    }
    
    /*!
     * @brief     To Set the CAN Buffer Setting(Filters and Masks)
     *
     * @param[in] None
     *
     * @return None
     */
    
    void
    mcp2515_initCANBuffers (void)
    {
        uint8_t i, a1, a2, a3;
    
        a1 = MCP_TXB0CTRL;
        a2 = MCP_TXB1CTRL;
        a3 = MCP_TXB2CTRL;
        for (i = 0; i < 14; i++)
            {
                mcp2515_setRegister (a1, 0);
                mcp2515_setRegister (a2, 0);
                mcp2515_setRegister (a3, 0);
                a1++;
                a2++;
                a3++;
            }
        mcp2515_setRegister (MCP_RXB0CTRL, 0);
        mcp2515_setRegister (MCP_RXB1CTRL, 0);
    }
    
    /*!
     * @brief     To initalize the CAN Module
     *
     * @param[in] Required Baud Rate of CAN.
     *
     * @return    0 : SUCESS 1: FAIL
     */
    
    uint8_t
    mcp2515_init (const uint8_t canSpeed)
    {
    
        uint8_t res;
    
        mcp_can_reset ();
    
        res = mcp2515_setCANCTRL_Mode (MODE_CONFIG);
    
        if (res > 0)
            {
                SEGGER_RTT_printf (0, "Enter setting mode fail\r\n");
    
                nrf_delay_ms (10);
    
                return res;
            }
    
        nrf_delay_ms (10);
    
        SEGGER_RTT_printf (0, "Enter setting mode success \r\n");
    
        if (mcp2515_configRate (canSpeed))
            {
    
                SEGGER_RTT_printf (0, "set rate fail!!\r\n");
    
                nrf_delay_ms (10);
    
                return res;
            }
    
        SEGGER_RTT_printf (0, "set rate Success!!\r\n");
    
        nrf_delay_ms (10);
    
        if (res == MCP2515_OK)
            {
    
                mcp2515_initCANBuffers ();
    
                mcp2515_setRegister (MCP_CANINTE, MCP_RX0IF | MCP_RX1IF);
    
    #if (DEBUG_RXANY == 1)
                /* enable both receive-buffers  */
                /* to receive any message       */
                /* and enable rollover          */
                mcp2515_modifyRegister (MCP_RXB0CTRL,
                    MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
                    MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
                mcp2515_modifyRegister (
                    MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_ANY);
    #else
    
                mcp2515_modifyRegister (MCP_RXB0CTRL,
                    MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
                    MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK);
                mcp2515_modifyRegister (
                    MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
    #endif
    
                res = mcp2515_setCANCTRL_Mode (MODE_NORMAL);
                if (res)
                    {
                        SEGGER_RTT_printf (0, "Enter Normal Mode Fail!!\r\n");
    #if DEBUG_MODE
                        printf ("Enter Normal Mode Fall!!\r\n");
    #else
                        nrf_delay_ms (10);
    #endif
                        return res;
                    }
    
                SEGGER_RTT_printf (0, "Enter Normal Mode Success!!\r\n");
    #if DEBUG_MODE
                printf ("Enter Normal Mode Success!!\r\n");
    #else
                nrf_delay_ms (10);
    #endif
            }
        return res;
    }
    
    /*!
     * @brief     Write the CAN Standard or extended Identifier
     *
     * @param[in] Address of Register
     * @parma[in] Flag for Extended identifier
     * @param[in] Identifer to set
     *
     * @return    None
     */
    
    void
    mcp2515_write_id (const uint8_t mcp_addr, const uint8_t ext, const uint32_t id)
    {
        uint16_t canid;
        uint8_t tbufdata[8];
    
        canid = (uint16_t) (id & 0x0FFFF);
    
        if (ext == 1)
            {
                tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF);
                tbufdata[MCP_EID8] = (uint8_t) (canid >> 8);
                canid = (uint16_t) (id >> 16);
                tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03);
                tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C) << 3);
                tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M;
                tbufdata[MCP_SIDH] = (uint8_t) (canid >> 5);
            }
        else
            {
    
                tbufdata[MCP_SIDH] = (uint8_t) (canid >> 3);
                tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07) << 5);
                tbufdata[MCP_EID0] = 0;
                tbufdata[MCP_EID8] = 0;
            }
        mcp2515_setRegisterS (mcp_addr, tbufdata, 4);
    }
    
    /*!
     * @brief     To read the ID of the incoming CAN Message
     *
     * @param[in] Address of Register
     * @parma[in] Flag for Extended identifier
     * @param[in] Identifer to Read
     *
     * @return    None
     */
    
    void
    mcp2515_read_id (const uint8_t mcp_addr, uint8_t *ext, uint32_t *id)
    {
        uint8_t tbufdata[4];
    
        *ext = 0;
        *id = 0;
    
        mcp2515_readRegisterS (mcp_addr, tbufdata, 4);
    
        *id = (tbufdata[MCP_SIDH] << 3) + (tbufdata[MCP_SIDL] >> 5);
    
        if ((tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M)
            {
    
                *id = (*id << 2) + (tbufdata[MCP_SIDL] & 0x03);
                *id = (*id << 8) + tbufdata[MCP_EID8];
                *id = (*id << 8) + tbufdata[MCP_EID0];
                *ext = 1;
            }
    }
    
    /*!
     * @brief     To Setup the CAN Messgae by setting Different Areas of CAN
     * Message
     *
     * @param[in] Address of Register
     *
     * @return    None
     */
    
    void
    mcp2515_write_canMsg (const uint8_t buffer_sidh_addr)
    {
    
        uint8_t mcp_addr;
        mcp_addr = buffer_sidh_addr;
        // write data bytes
        mcp2515_setRegisterS (mcp_addr + 5, m_mcp_can.m_data, m_mcp_can.m_len);
        // write the RTR and DLC
        mcp2515_setRegister ((mcp_addr + 4), m_mcp_can.m_len);
        // write CAN id
        mcp2515_write_id (mcp_addr, m_mcp_can.m_ext_flag, m_mcp_can.m_id);
    }
    
    /*!
     * @brief     To Read the CAN Message
     *
     * @param[in] Address of Register
     *
     * @return    None
     */
    
    void
    mcp2515_read_canMsg (const uint8_t buffer_sidh_addr)
    {
        uint8_t mcp_addr, ctrl;
    
        mcp_addr = buffer_sidh_addr;
    
        mcp2515_read_id (mcp_addr, &m_mcp_can.m_ext_flag, &m_mcp_can.m_id);
    
        ctrl = mcp2515_readRegister (mcp_addr - 1);
        m_mcp_can.m_len = mcp2515_readRegister (mcp_addr + 4);
    
        m_mcp_can.m_len &= MCP_DLC_MASK;
        mcp2515_readRegisterS (
            mcp_addr + 5, &(m_mcp_can.m_data[0]), m_mcp_can.m_len);
    }
    
    /*!
     * @brief     To start the transmission of message via CAN
     *
     * @param[in] Address of Transmit Register
     *
     * @return    None
     */
    
    void
    mcp2515_start_transmit (const uint8_t mcp_addr)
    {
    
        mcp2515_modifyRegister (mcp_addr - 1, MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M);
    }
    
    /*!
     * @brief     To Get the next free Tx Buffer ,if previous one is filled
     *
     * @param[in] Address of Transmit Buffer Register
     *
     * @return    0 : OK , 2 : All Buffer Full
     */
    
    uint8_t
    mcp2515_getNextFreeTXBuf (uint8_t *txbuf_n)
    {
    
        uint8_t res, i, ctrlval;
        uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL,
            MCP_TXB2CTRL };
    
        res = MCP_ALLTXBUSY;
        *txbuf_n = 0x00;
    
        // check all 3 TX-Buffers
        for (i = 0; i < MCP_N_TXBUFFERS; i++)
            {
                ctrlval = mcp2515_readRegister (ctrlregs[i]);
                if ((ctrlval & MCP_TXB_TXREQ_M) == 0)
                    {
                        *txbuf_n = ctrlregs[i] + 1;
    
                        res = MCP2515_OK;
                        return res;
                    }
            }
        return res;
    }
    
    /*!
     * @brief     To Load the message into Global Structure Variables
     *
     * @param[in] Identifier to send the message with
     * @param[in] Flag for Extended Identifier
     * @param[in] Length of Data to be sent
     * @param[in] Address of the pointer data to be sent
     *
     * @return    0 : OK
     */
    
    uint8_t
    setMsg (uint32_t id, uint8_t ext, uint8_t len, uint8_t *pData)
    {
        int i = 0;
        m_mcp_can.m_ext_flag = 0; // ext;
        m_mcp_can.m_id = id;
        m_mcp_can.m_len = len;
        for (i = 0; i < MAX_CHAR_IN_MESSAGE; i++)
            {
                m_mcp_can.m_data[i] = *(pData + i);
            }
        return MCP2515_OK;
    }
    
    /*!
     * @brief     To Clear the message parameters
     *
     * @param[in] None
     *
     * @return    0 : OK
     */
    
    uint8_t
    clearMsg ()
    {
        m_mcp_can.m_id = 0;
        m_mcp_can.m_len = 0;
        m_mcp_can.m_ext_flag = 0;
        for (int i = 0; i < m_mcp_can.m_len; i++)
            m_mcp_can.m_data[i] = 0x00;
    
        return MCP2515_OK;
    }
    
    /*!
     * @brief     To Send the message via CAN Bus
     *
     * @param[in] None
     *
     * @return    0 : OK , 7 : Messge Sent Timeout , 6 : Buffer Full Timoeut
     */
    
    uint8_t
    sendMsg ()
    {
        uint8_t res, res1, txbuf_n;
        uint16_t uiTimeOut = 0;
    
        do
            {
                res = mcp2515_getNextFreeTXBuf (&txbuf_n);
    
                uiTimeOut++;
            }
        while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE));
    
        if (uiTimeOut == TIMEOUTVALUE)
            {
                spi_master_uninit ();
                return CAN_GETTXBFTIMEOUT;
    
            }
        uiTimeOut = 0;
       // SEGGER_RTT_printf (0, "TXBUFFER :%x\r\n", txbuf_n);
        mcp2515_write_canMsg (txbuf_n);
        mcp2515_start_transmit (txbuf_n);
        do
            {
                uiTimeOut++;
                res1 = mcp2515_readRegister (txbuf_n - 1);
    
                res1 = res1 & 0x08;
            }
        while (res1 && (uiTimeOut < TIMEOUTVALUE));
        if (uiTimeOut == TIMEOUTVALUE)
            {
                spi_master_uninit ();
                return CAN_SENDMSGTIMEOUT;
            }
        spi_master_uninit ();
    
        return CAN_OK;
    }
    
    /*!
     * @brief     To Read the incoming message
     *
     * @param[in] None
     *
     * @return    0 : OK , 4 : No message was Received
     */
    
    uint8_t
    readMsg ()
    {
        uint8_t stat, res;
    
        stat = mcp2515_readStatus ();
    
        if (stat & MCP_STAT_RX0IF)
            {
                mcp2515_read_canMsg (MCP_RXBUF_0);
                mcp2515_modifyRegister (MCP_CANINTF, MCP_RX0IF, 0);
                res = CAN_OK;
            }
        else if (stat & MCP_STAT_RX1IF)
            {
                mcp2515_read_canMsg (MCP_RXBUF_1);
                mcp2515_modifyRegister (MCP_CANINTF, MCP_RX1IF, 0);
                res = CAN_OK;
            }
        else
            {
                res = CAN_NOMSG;
            }
        return res;
    }
    
    // NOTE : THIS FUNCTION IS NOT CALLED ANYWHERE , JUST TO BE SAFE I AM NOT
    // DELETING IT :p
    
    void
    mcp_can_setcs (uint8_t cs)
    {
        m_mcp_can.m_cs = cs;
        nrf_gpio_cfg_output (m_mcp_can.m_cs);
        mcp_unselect ();
    }
    
    /*!
     * @brief     To Initialize the CAN With Required Baud Rate
     *
     * @param[in] Baud Rate Required
     *
     * @return    0 : OK , 1 : Failed Initializing
     */
    
    uint8_t
    mcp_can_begin (uint8_t speedset)
    {
        uint8_t res;
    
        spi_master_init (SPI_MASTER_0, spi_master_0_event_handler);
    
        res = mcp2515_init (speedset);
        
        spi_master_uninit ();
        if (res == MCP2515_OK)
            return CAN_OK;
        else
            return CAN_FAILINIT;
    }
    
    /*!
     * @brief     To send the message by first creating the format
     *
     * @param[in] Identifier with which message will be sent
     * @param[in] Flag for extended identifier
     * @param[in] Length of data to be Sent
     * @param[in] Address of Pointer to data which is needed to be sent
     *
     * @return    Value Retuned by sendMsg() Function
     */
    
    uint8_t
    mcp_can_send_msg (uint32_t id, uint8_t ext, uint8_t len, uint8_t *buf)
    {   
        spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
        setMsg (id, ext, len, buf);
        return sendMsg ();
    }
    
    /*!
     * @brief     To Read the CAN Message
     *
     * @param[in] Identifier To store the id of message
     * @param[in] Length to be received
     * @param[in] Buffer to store the received Data
     *
     * @return    Value Retuned by readMsg() Function
     */
    
    uint8_t
    mcp_can_read_msg (uint32_t *ID, uint8_t *len, uint8_t buf[])
    {
        uint8_t rc;
        spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
        rc = readMsg ();
    
        if (rc == CAN_OK)
            {
                *len = m_mcp_can.m_len;
                *ID = m_mcp_can.m_id;
                for (int i = 0; i < m_mcp_can.m_len && i < MAX_CHAR_IN_MESSAGE;
                     i++)
                    {
                        buf[i] = m_mcp_can.m_data[i];
                    }
            }
        else
            {
                *len = 0;
            }
        spi_master_uninit ();
        return rc;
    }
    
    /*!
     * @brief     To Check the Receive Message Register
     *
     * @param[in] None
     *
     * @return    3 : Message AVailable , 4 : No Message Available
     */
    
    uint8_t
    mcp_can_check_receive (void)
    {
        uint8_t res;
        spi_master_init (SPI_MASTER_0,spi_master_0_event_handler);
        res = mcp2515_readStatus ();
        spi_master_uninit ();
        if (res & MCP_STAT_RXIF_MASK)
            {
                return CAN_MSGAVAIL;
            }
        else
            {
                return CAN_NOMSG;
            }
    }
    
    /*!
     * @brief     To Check if any Error Occured on Bus
     *
     * @param[in] None
     *
     * @return    5 : CAN CONTROL REGISTER ERROR , 0 : OK
     */
    
    uint8_t
    mcp_can_check_error (void)
    {
        uint8_t eflg = mcp2515_readRegister (MCP_EFLG);
    
        if (eflg & MCP_EFLG_ERRORMASK)
            {
                return CAN_CTRLERROR;
            }
        else
            {
                return CAN_OK;
            }
    }

    you can take refernce from this file , it won't compile on your end ,because it needs other header files and stuff , But it can help you with few things i hope

    Thanks

  • Also , for me memset was creating few issues when i used spi , you should try using nrf_memset function.

    Maybe that helps

  • Thanks.

    where is it defined? I couldn't find the function nrf_memset.

Related