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

📄 can_accfilt_lpc2xxx.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
    } // if (pLine < pExtGrpStart)
          
    if (CAN_ACCFILT_EFF_GRP_SA == Table)
    {
        //
        // If we are in the area of extended groups then we need to insert
        // 2 lines because lower and upper identifier need 1 line each
        //
        entry_size += sizeof(cyg_uint32); // one entry is 2 dword long
    }
    
    entry_address = end_of_table - sizeof(cyg_uint32);
    end_of_table  += entry_size;  // add one additional entry
        
    //
    // Move alle entries one or two dwords upwards - that means we insert a new empty line
    //
    while (entry_address >= copy_start)
    {
        HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
        HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address + entry_size, lsc_val.dword);
        entry_address -= sizeof(cyg_uint32);  
    }
    
    //
    // For the std ID area we need a special pocedure
    //
    if (CAN_ACCFILT_SFF_SA == Table)
    {
        lsc_buf_t preval;
        //
        // Start copy with last entry of std id table
        //
        entry_address = sff_grp_sa - sizeof(cyg_uint32);    
                
        while (entry_address > insert_address)
        {
            HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
            HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address - sizeof(cyg_uint32), preval.dword);
            lsc_val.column.upper = lsc_val.column.lower;
            lsc_val.column.lower = preval.column.upper;
            HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
            entry_address -= sizeof(cyg_uint32);
        }
        
        //
        // If we insert an entry into the lower colum, then we need to move the
        // content of the lower column into the upper column
        //
        if (!(EntryNo % 2))
        {
            HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword);
            lsc_val.column.upper = lsc_val.column.lower;
            HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword);
        }
        
        //
        // If we inserted a new line, then we have an odd number of identifiers now
        // and need to disable the last (the upper) entry
        //
        if (entry_size)
        {
            HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword);
            lsc_val.column.upper = 0xFFFF;  // disable the entry
            HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword);
        }
    }
    
    HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
    HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
    HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);      
    HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
    HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
}


//===========================================================================
// Query number of entries in a certain table
//===========================================================================
static cyg_uint16 lpc2xxx_can_accfilt_get_table_entries(cyg_uint32 TableStartAddress)
{
    cyg_uint32  start;
    cyg_uint32  end;
    
    switch (TableStartAddress)
    {
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
    case CAN_ACCFILT_SFF_SA:
         HAL_READ_UINT32(CAN_ACCFILT_SFF_SA,     start);
         HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, end);
         if (end - start)
         {
             lsc_buf_t data;
             HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + end - sizeof(cyg_uint32), data.dword);
             if (data.column.upper & ACCFILT_STD_DIS)
             {
                 return (((end - start) >> 1) - 1);
             }
         }
         return (end - start) >> 1;
         
    case CAN_ACCFILT_SFF_GRP_SA:
         HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, start);
         HAL_READ_UINT32(CAN_ACCFILT_EFF_SA,     end);
         return (end - start) >> 2;
#endif // CYGOPT_IO_CAN_STD_CAN_ID

#ifdef CYGOPT_IO_CAN_EXT_CAN_ID        
    case CAN_ACCFILT_EFF_SA:
         HAL_READ_UINT32(CAN_ACCFILT_EFF_SA,     start);
         HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, end);
         return (end - start) >> 2;
                 
    case CAN_ACCFILT_EFF_GRP_SA:
         HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, start);
         HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end);
         return (end - start) >> 3;
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
    default:
        CYG_FAIL("Invalid identifier table address");
        return 0;         
    } // switch (TableStartAddress)
}

//===========================================================================
// Query certain entry from table
//===========================================================================
static void lpc2xxx_can_accfilt_get_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry)
{
    cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
    lsc_buf_t  Data;

    HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
    pEntry->data = Data.dword;
    switch (TableStartAddress)
    {
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
    case CAN_ACCFILT_SFF_SA:
    {
         cyg_uint16 column; 
         if (EntryNo % 2)
         {
             column = Data.column.upper;
         }
         else
         {
             column = Data.column.lower; 
         }
         pEntry->id         = ACCFILT_STD_GET_ID(column);
         pEntry->channel_no = ACCFILT_STD_GET_CTRL(column);
    }
    break;
                 
    case CAN_ACCFILT_SFF_GRP_SA:
         pEntry->lower_id_bound = ACCFILT_STD_GET_ID(Data.column.lower);
         pEntry->upper_id_bound = ACCFILT_STD_GET_ID(Data.column.upper);
         pEntry->channel_no     = ACCFILT_STD_GET_CTRL(Data.column.lower);
         break;
#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
    
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
    case CAN_ACCFILT_EFF_SA:
         pEntry->id         = ACCFILT_EXT_GET_ID(Data.dword);
         pEntry->channel_no = ACCFILT_EXT_GET_CTRL(Data.dword);
         break;
                        
    case CAN_ACCFILT_EFF_GRP_SA:
         pEntry->lower_id_bound = ACCFILT_EXT_GET_ID(Data.dword);
         pEntry->channel_no     = ACCFILT_EXT_GET_CTRL(Data.dword);
         HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE+ EntryAddress + sizeof(cyg_uint32), Data.dword);
         pEntry->upper_id_bound = ACCFILT_EXT_GET_ID(Data.dword);
         break;
#endif // #ifedf CYGOPT_IO_CAN_EXT_CAN_ID
    default:
        CYG_FAIL("Invalid identifier table address");
    } // switch ()
}


//===========================================================================
// Set certain entry in table
//===========================================================================
static void lpc2xxx_can_accfilt_set_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry)
{
    cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
    lsc_buf_t Data;

    switch (TableStartAddress)
    {
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
    case CAN_ACCFILT_SFF_SA:
         {
             HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);            
             if (EntryNo % 2)
             {
                 Data.column.upper = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
             }
             else
             {
                 Data.column.lower = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
             }
         }
         break;
                 
    case CAN_ACCFILT_SFF_GRP_SA:
         Data.column.lower = (pEntry->channel_no << 13) | (pEntry->lower_id_bound & ACCFILT_STD_ID_MASK);
         Data.column.upper = (pEntry->channel_no << 13) | (pEntry->upper_id_bound & ACCFILT_STD_ID_MASK);
         break;
#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID

#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
    case CAN_ACCFILT_EFF_SA:
         Data.dword = (pEntry->channel_no << 29) | (pEntry->id & ACCFILT_EXT_ID_MASK); 
         break;
                        
    case CAN_ACCFILT_EFF_GRP_SA:
         {
             lsc_buf_t Data2;
             
             Data.dword  = (pEntry->channel_no << 29) | (pEntry->lower_id_bound & ACCFILT_EXT_ID_MASK);
             Data2.dword = (pEntry->channel_no << 29) | (pEntry->upper_id_bound & ACCFILT_EXT_ID_MASK);
             HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress + sizeof(cyg_uint32), Data2.dword);
         }
         break;
#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
         
    default:
        CYG_FAIL("Invalid identifier table address");
    } // switch ()
    
    HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
}


//===========================================================================
// Add one entry to acceptance filter RAM
// If upper ID is > lower ID then we have to add a group filter - else we
// have to add a single message filter here
//===========================================================================
static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info, 
                                    cyg_uint32          lower_id, 
                                    cyg_uint32          upper_id, 
                                    cyg_can_id_type     ext)
{
    cyg_uint32              accfilt_bck; // acceptance filter backup
    cyg_uint32              end_of_table;
    cyg_uint32              table;
    lpc2xxx_accfilt_entry_t entry;
    lpc2xxx_accfilt_entry_t new_entry;
    
    
    //
    // first step: disable acceptance filter and prepare it for modification
    //
    HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
    HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
    
    //
    // Check if table is full
    //
    HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
    if (end_of_table >= ACCFILT_RAM_SIZE)
    {
        return false;   
    }
    
    new_entry.id             = lower_id;
    new_entry.lower_id_bound = lower_id;
    new_entry.upper_id_bound = upper_id;
    
    //
    // Here we rely on the ISR vector ordering for calculaion of of channel number
    // Maybe this is not the right way for newer LPC parts
    //
    new_entry.channel_no = (CAN_ISRVEC(info) - CYGNUM_HAL_INTERRUPT_CAN1_TX) + 1; 
    
    //
    // If lower_id == upper_id then we know that we have to setup a single message filter 
    // here. If it is not equal the it is group of identifiers to receive
    //
    if ((lower_id == upper_id) || (lower_id > upper_id))
    {
        //
        // setup single message filter (standard or extended) here
        //
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
        if (ext)
        {
            table = CAN_ACCFILT_EFF_SA;
        }
        else
#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
        {
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
            table = CAN_ACCFILT_SFF_SA;
#endif // CYGOPT_IO_CAN_STD_CAN_ID
        }
    }
    else
    {
        //
        // setup single message filter (standard or extended) here
        //
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
        if (ext)
        {
            table = CAN_ACCFILT_EFF_GRP_SA;
        }
        else
#endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
        {
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
            table = CAN_ACCFILT_SFF_GRP_SA;
#endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
        }
    }
        
    cyg_uint16 entries = lpc2xxx_can_accfilt_get_table_entries(table);
    cyg_uint16 i;
    
           
    for (i = 0; i < entries; ++i)
    {
        lpc2xxx_can_accfilt_get_entry(table, i, &entry);

        if (entry.channel_no > new_entry.channel_no)
        {
            break;
        }
        

⌨️ 快捷键说明

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