⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can_at91sam7.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:


//===========================================================================
// Stop transmitter
//===========================================================================
static void at91sam7_can_stop_xmit(can_channel* chan)
{
     CAN_DECLARE_INFO(chan);
    
     HAL_WRITE_UINT32(CAN_IDR(info), 0x01 << CAN_MBOX_TX(info)); // disable tx interrupt 
     AT91SAM7_DBG_PRINT("stop_xmit\n");   
}


//===========================================================================
// Configure can channel
//===========================================================================
static bool at91sam7_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
{
    CAN_DECLARE_INFO(chan);
    cyg_uint32 temp32;
    bool       res = true;
    
    if (init)
    {
    	//
    	// If the platform that uses the driver needs to do some platform specific
    	// initialisation steps, it can do it inside of this macro. I.e. some platforms
    	// need to setup the CAN transceiver properly here (this is necessary for the
    	// Atmel AT91SAM7X-EK)
    	//
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
        HAL_AT91SAM7_CAN0_PLF_INIT();
#else // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1
#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
        if (info == &at91sam7_can0_info) {
            HAL_AT91SAM7_CAN0_PLF_INIT();
        }
#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN1) && defined(HAL_AT91SAM7_CAN1_PLF_INIT)
        if (info == &at91sam7_can1_info) {
            HAL_AT91SAM7_CAN1_PLF_INIT();
        }
#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
#endif // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1

        HAL_WRITE_UINT32(CAN_IDR(info), 0xFFFFFFFF);   // disable all interrupts
        HAL_WRITE_UINT32(CAN_MR(info), 0x00);          // disable CAN module
        HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANRX);          // Enable the CAN module to drive the CAN port pins
        HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANTX);      
            
        HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_DISABLED); // first disable tx message box
        HAL_WRITE_UINT32(CAN_MB_MAM(info, CAN_MBOX_TX(info)), 0x00000000);           // set acceptance mask once
        HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_TX);       // setup as tx message box
        
        HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE); // enable CAN module  
        
        //
        // The device should go into error active state right after enabling it
        //
        HAL_READ_UINT32(CAN_SR(info), temp32);
        if (!(temp32 & INT_ERR_ACTIVE))
        {
            res = false;
        }   
    } // if (init)
    
    res = at91sam7_can_set_baud(chan, &config->baud);        // set baudrate
            
    //
    // store new config values
    //
    if (config != &chan->config) 
    {
        chan->config = *config;
    }   
    
    return res;
}


//===========================================================================
// Low level interrupt handler
//===========================================================================
static cyg_uint32 at91sam7_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
    can_channel                 *chan    = (can_channel *)data;
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
    cyg_uint32                   sr;
    cyg_uint32                   imr;
    
    
    HAL_READ_UINT32(CAN_IMR(info), imr);
    HAL_READ_UINT32(CAN_SR(info), sr);
    AT91SAM7_DBG_PRINT("CAN_ISR SR %x\n", sr);   
    sr &= imr;
    HAL_WRITE_UINT32(CAN_IDR(info), sr);
   
    info->stat |= sr;
    cyg_drv_interrupt_acknowledge(vector);
    return CYG_ISR_CALL_DSR;
}


//===========================================================================
// High level interrupt handler
//===========================================================================
static void at91sam7_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
    can_channel                 *chan    = (can_channel *)data;
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
    cyg_uint32                   stat = 0;
       
    do
    {   
        //
        // If a number of events occured then we process all events now in
        // in this DSR the get_event() function clears the flags in the stat
        // field
        //
        while (stat)
        {
            if (stat & (0x01 << CAN_MBOX_TX(info)))
            {
                AT91SAM7_DBG_PRINT("TX_DSR\n");    
                chan->callbacks->xmt_msg(chan, 0);   // send next message 
                stat &= ~INT_MB_TX;                  // clear flag
            }
            else if (stat)
            {
                AT91SAM7_DBG_PRINT("EVENT_DSR\n");   
                chan->callbacks->rcv_event(chan, &stat);
            }
        }
        
        //
        // We check, if a new event occured while we processed other events. If new events
        // occured, then we process the new events
        //
        cyg_drv_interrupt_mask(vector);
        stat = info->stat;
        info->stat = 0;
        cyg_drv_interrupt_unmask(vector);
    } while (stat);
}


//===========================================================================
// Set baudrate of certain can channel
//===========================================================================
static bool at91sam7_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate)
{
    bool                  res = true;
    cyg_uint32            mrbck;
    cyg_uint32            canbr;
    CAN_DECLARE_INFO(chan);


#ifdef CYGOPT_IO_CAN_AUTOBAUD  
    if (CYGNUM_CAN_KBAUD_AUTO == *baudrate)
    {   
        cyg_can_baud_rate_t   i;
        cyg_uint8             j;
        cyg_uint32            sr;
        
        res = false;
        for (i = CYGNUM_CAN_KBAUD_10; i <= CYGNUM_CAN_KBAUD_1000; ++i)
        {
            HAL_AT91SAM7_GET_CAN_BR(i, canbr);
            if (0 == canbr)
            {
                continue;
            }  
                      
            HAL_READ_UINT32(CAN_SR(info), sr);
            HAL_WRITE_UINT32(CAN_MR(info), 0);                            // disable the module
            HAL_WRITE_UINT32(CAN_BR(info), canbr);                        // write baudrate register
            HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE | MR_AUTOBAUD);  // enable controller in auto aud mode
            for(j = 0; j < 200; ++j)
            {
                HAL_DELAY_US(1000);                                       // wait at least 11 bit times for synchronization
            }
            HAL_READ_UINT32(CAN_SR(info), sr);                            // read status register
            if (!(sr & INT_ALL_ERR) && (sr & INT_WAKEUP))
            {
                HAL_WRITE_UINT32(CAN_MR(info), 0);                        // disable the module 
                HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE);            // enable controller
                *baudrate = i;                                            // store baudrate
                return true;
            } // if (!(sr & INT_ALL_ERR))         
        }
    }
    else
#endif // CYGOPT_IO_CAN_AUTOBAUD 
    { 
        //
        // Get bit timings from HAL because bit timings depend on sysclock
        // For main clock of 48 MHz this macro is implemented in this device
        // driver. If the macro fills the canbr value with 0 then the baudrate
        // is not supported and the function returns false
        //
        HAL_AT91SAM7_GET_CAN_BR(*baudrate, canbr);   
        if (0 == canbr)
        {
            return false;
        }
        
        //
        // Any modificatons to the baudrate register must be done while CAN
        // module is disabled. So we first disable CAN module, then we set
        // baudrate and then we reenable the CAN module by setting the CAN enable
        // flag
        //
        HAL_READ_UINT32(CAN_MR(info), mrbck);                   // backup value of mode register
        HAL_WRITE_UINT32(CAN_MR(info), mrbck &~MR_CAN_ENABLE);  // disable controller
        HAL_WRITE_UINT32(CAN_BR(info), canbr);                  // write baudrate register
        
        //
        // Now restore the previous state - if the module was started then
        // it will no be started again, if it was stopped, then it remains stopped
        //
        HAL_WRITE_UINT32(CAN_MR(info), mrbck);
    }
    
    return res;
}


//===========================================================================
// Setup one single message box for reception of can message
//===========================================================================
static void at91sam7_can_setup_mbox(can_channel *chan, cyg_uint8 mbox, cyg_uint32 mid, cyg_uint32 mam, cyg_uint32 rxtype)
{
    CAN_DECLARE_INFO(chan);
    CYG_ASSERT(mbox < 7, "invalid rx mbox number");
    
  
    //
    // To prevent concurrent access with the internal CAN core, the application
    // must disable the mailbox before writing to CAN_MIDx registers - so we
    // do this here
    //
    HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), MMR_MB_TYPE_DISABLED); // first disable message box
    HAL_WRITE_UINT32(CAN_MB_MAM(info, mbox), mam);                  // set acceptance mask
    HAL_WRITE_UINT32(CAN_MB_MID(info, mbox), mid);                  // set message identifier                          
    HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), rxtype);               // setup message box as rx message box (with or without overwrite)
    HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), MCR_TRANSFER_CMD);     // transfer request - we do not enable interrupts here
}


//===========================================================================
// Configure message boxes for reception of any CAN message
//===========================================================================
static void at91sam7_can_mbox_config_rx_all(can_channel *chan)
{
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
    cyg_uint8  i;
    cyg_uint8  mbox_int_mask    = 0;
    cyg_uint8  mbox_rx_all_cnt  = CAN_MBOX_RX_ALL_CNT(info);
#ifdef CYGOPT_IO_CAN_STD_CAN_ID 
    cyg_uint8  last_std_rx_mbox = CAN_MBOX_STD_CNT(info) - 1;
#endif // CYGOPT_IO_CAN_STD_CAN_ID
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
    cyg_uint8  last_ext_rx_mbox = mbox_rx_all_cnt - 1;
#endif// CYGOPT_IO_CAN_EXT_CAN_ID 

    //
    // Now setup all rx message boxes. One message box (the last one - no 8) is
    // used for transmission so we have 7 message boxes for reception of can messages
    // We setup the message boxes 0 - 5 as RX mboxes and message box 6 as RX mbox with
    // overwrite. 
    //    
    for (i = 0; i < mbox_rx_all_cnt; ++i)
    { 
#ifdef CYGOPT_IO_CAN_STD_CAN_ID     
        if (i < CAN_MBOX_STD_CNT(info))
        {
            //
            // setup message boxes for standard frames
            //
            if (i < last_std_rx_mbox) 
            {
                at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX);
            }
            else
            {
                at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX_OVW);
            }
        }
        else
#endif // CYGOPT_IO_CAN_STD_CAN_ID 
        {
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
            //
            // setup message boxes for extended frames
            //
            if (i < last_ext_rx_mbox)
            {
                at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX);
            }
            else
            {
                at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX_OVW);
            }
#endif// CYGOPT_IO_CAN_EXT_CAN_ID 
        } // if (i < CAN_MBOX_STD_CNT(info))
        
        mbox_int_mask = (mbox_int_mask << 1) | 0x01; // enable interrupt 
    } // for (i = 0; i < CAN_MBOX_RX_CNT; ++i)*/
    
    info->free_mboxes = CAN_MBOX_RX_CNT - mbox_rx_all_cnt;
    info->rx_all      = true;
    HAL_WRITE_UINT32(CAN_IER(info), mbox_int_mask); // Now finally enable the interrupts for als RX mboxes
}


//---------------------------------------------------------------------------
// EOF can_at91am7.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -