📄 can_accfilt_lpc2xxx.c
字号:
//==========================================================================
//
// devs/can/arm/lpc2xxx/current/src/can_accfilt_lpc2xxx.c
//
// Acceptance filter management for LPC2xxx CAN driver
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Uwe Kindler
// Contributors: Uwe Kindler
// Date: 2007-05-28
// Purpose: Support LPC2xxx on-chip CAN acceptance filters
// Description:
//
//####DESCRIPTIONEND####
//
//==========================================================================
//===========================================================================
// Data types
//===========================================================================
//
// Acceptance filter entry
//
typedef struct lpc2xxx_accfilt_entry
{
cyg_uint32 data; // the value inclusive channel number
cyg_uint32 id;
cyg_uint32 lower_id_bound;
cyg_uint32 upper_id_bound;
cyg_uint8 channel_no;
} lpc2xxx_accfilt_entry_t;
//===========================================================================
// Declarations
//===========================================================================
//--------------------------------------------------------------------------
// Lowlevel acceptance filter access
//
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info,
cyg_uint32 lower_id,
cyg_uint32 upper_id,
cyg_can_id_type ext);
void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo);
void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo);
void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info);
#else
static void lpc2xxx_can_accfilt_simple_rx_all(void);
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
void lpc2xxx_can_accfilt_reset(void);
#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
void lpc2xxx_can_accfilt_dbg_dump(void);
void lpc2xxx_can_reg_dump(struct cyg_devtab_entry* devtab_entry);
#endif
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
//===========================================================================
// Calculate address of entry in certain table
//===========================================================================
static cyg_uint32 lpc2xxx_can_accfilt_calc_entry_address(cyg_uint32 TableAddressRegister, cyg_uint16 EntryNo)
{
cyg_uint32 EntryAddress = 0xFFFFFFFF;
cyg_uint32 TableAddress;
HAL_READ_UINT32(TableAddressRegister, TableAddress);
switch (TableAddressRegister)
{
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
case CAN_ACCFILT_SFF_SA:
EntryAddress = ((EntryNo / 2) << 2) + TableAddress;
break;
case CAN_ACCFILT_SFF_GRP_SA:
EntryAddress = TableAddress + (EntryNo << 2);
break;
#endif // CYGOPT_IO_CAN_STD_CAN_ID
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
case CAN_ACCFILT_EFF_SA:
EntryAddress = TableAddress + (EntryNo << 2);
break;
case CAN_ACCFILT_EFF_GRP_SA:
EntryAddress = TableAddress + (EntryNo << 3);
break;
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
default:
CYG_ASSERT(0, "Wrong TableAddressRegister");
}
return EntryAddress;
}
//===========================================================================
// Remove one single entry from acceptance filter table
//===========================================================================
void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 Table, cyg_uint16 EntryNo)
{
cyg_int32 remove_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo);
cyg_int32 entry_address;
lsc_buf_t lsc_val;
cyg_uint8 entry_size = sizeof(cyg_uint32);
cyg_uint32 sff_sa;
cyg_uint32 sff_grp_sa;
cyg_uint32 eff_sa;
cyg_uint32 eff_grp_sa;
cyg_int32 end_of_table;
HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
//
// Do not try to remove from an empty table
//
if (!end_of_table)
{
return;
}
entry_address = remove_address;
if ((remove_address < eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
{
if ((remove_address < eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
{
if ((remove_address < sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
{
lsc_buf_t nextval;
if (EntryNo % 2)
{
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address, lsc_val.dword);
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address + sizeof(cyg_uint32), nextval.dword);
lsc_val.column.upper = nextval.column.lower;
entry_address += sizeof(cyg_uint32);
}
//
// Start copy immediatelly after removed entry
//
while (entry_address < sff_grp_sa)
{
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + sizeof(cyg_uint32), nextval.dword);
lsc_val.column.lower = lsc_val.column.upper;
lsc_val.column.upper = nextval.column.lower;
HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
entry_address += sizeof(cyg_uint32);
}
//
// now check if the lower identifier is disabled - if it is disabled, then
// also the upper identifier is invalid and we can remove the entry completely
// if the lower identifier is not disabled, then it is valid and we need
// to disable the upper identifier because it contains an invalid entry
//
if (lsc_val.column.lower & ACCFILT_STD_DIS)
{
sff_grp_sa -= sizeof(cyg_uint32);
entry_address = sff_grp_sa;
}
else
{
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword);
lsc_val.column.upper = 0xffff;
HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword);
entry_size = 0; // we do not need to remove anything
}
} // if (pLine < pStdGrpStart)
eff_sa -= entry_size;
} // if (pLine < pExtIdStart)
eff_grp_sa -= entry_size;
} // if (pLine < pExtGrpStart)
//
// If no entry was removed then we can leave immediatelly without changing any
// table pointers because we only did a change inside the sff table
//
if (!entry_size)
{
#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
lpc2xxx_can_accfilt_dbg_dump();
#endif
return;
}
if (CAN_ACCFILT_EFF_GRP_SA == Table)
{
//
// If we are in the area of extended groups then we need to remove
// 2 lines because lower and upper identifier need 1 line each
//
entry_size += sizeof(cyg_uint32);
}
end_of_table -= entry_size;
//
// Move alle entries one or two dword downwads - that means we remove a line
//
while (entry_address < end_of_table)
{
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + entry_size, lsc_val.dword);
HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
entry_address += sizeof(cyg_uint32);
}
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);
#ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
lpc2xxx_can_accfilt_dbg_dump();
#endif
}
//===========================================================================
// Insert one empty line into ram - all entries behind this line will be
// moved one entry upwards
//===========================================================================
void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 Table, cyg_uint16 EntryNo)
{
cyg_int16 insert_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo);
cyg_int16 entry_address;
cyg_int16 copy_start = insert_address;
lsc_buf_t lsc_val;
cyg_uint8 entry_size = sizeof(cyg_uint32);
cyg_uint32 sff_sa;
cyg_uint32 sff_grp_sa;
cyg_uint32 eff_sa;
cyg_uint32 eff_grp_sa;
cyg_uint32 end_of_table;
HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
if ((insert_address <= eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
{
if ((insert_address <= eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
{
if ((insert_address <= sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
{
//
// If we are in the range of standard identifiers then we need to
// do some special copy procedure for this area because a standard entry
// is only 2 byte long. Copy only til start of area with standard groups
//
if (sff_grp_sa)
{
HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); // read last entry
//
// now check if the upper identifier is disabled - if it is disabled, then
// we have an odd number of std ids in the list. Then we do not need to
// insert a new line - we simply need to copy all entries 2 bytes upwards
// that meeans we only need to change the std id area and do not need to touch
// any other filter id area.
// If the last entry is not disabled, then we have a valid filter here.
// Then we need to insert a complete new line, that means we also have to mave
// all following entries and filter tables one dword upwards.
//
if (lsc_val.words.low & ACCFILT_STD_DIS)
{
copy_start = end_of_table + sizeof(cyg_uint32); // we do not need to insert a new line and do not copy anything
entry_size = 0;
}
}
if (entry_size)
{
copy_start = sff_grp_sa; // copy everything behind std id group
sff_grp_sa += entry_size;
}
} // if (pLine < pStdGrpStart)
eff_sa += entry_size;
} // if (pLine < pExtIdStart)
eff_grp_sa += entry_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -