📄 sa11x0_misc.c
字号:
}
//
// Interrupt control
//
void hal_interrupt_mask(int vector)
{
#ifdef HAL_EXTENDED_INTERRUPT_MASK
// Use platform specific handling, if defined
// Note: this macro should do a 'return' for "extended" values of 'vector'
// Normal vectors are handled by code subsequent to the macro call.
HAL_EXTENDED_INTERRUPT_MASK(vector);
#endif
// Non-GPIO interrupt sources can be masked separately.
// Note: masking any non-unique GPIO signal (31..11) results in
// all GPIO signals (31..11) being masked as only the "lump"
// source will be changed.
if (vector >= CYGNUM_HAL_INTERRUPT_GPIO11) {
vector = CYGNUM_HAL_INTERRUPT_GPIO;
}
*SA11X0_ICMR &= ~(1 << vector);
}
void hal_interrupt_unmask(int vector)
{
#ifdef HAL_EXTENDED_INTERRUPT_UNMASK
// Use platform specific handling, if defined
// Note: this macro should do a 'return' for "extended" values of 'vector'
// Normal vectors are handled by code subsequent to the macro call.
HAL_EXTENDED_INTERRUPT_UNMASK(vector);
#endif
if (vector >= CYGNUM_HAL_INTERRUPT_GPIO11) {
vector = CYGNUM_HAL_INTERRUPT_GPIO;
}
*SA11X0_ICMR |= (1 << vector);
}
void hal_interrupt_acknowledge(int vector)
{
#ifdef HAL_EXTENDED_INTERRUPT_UNMASK
// Use platform specific handling, if defined
// Note: this macro should do a 'return' for "extended" values of 'vector'
// Normal vectors are handled by code subsequent to the macro call.
HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
#endif
// GPIO interrupts are driven by an edge detection mechanism. This
// is latching so these interrupts must be acknowledged directly.
// All other interrupts simply go away when the interrupting unit
// has been serviced by the ISR.
if ((vector < CYGNUM_HAL_INTERRUPT_GPIO) ||
(vector >= CYGNUM_HAL_INTERRUPT_GPIO11)) {
*SA11X0_GPIO_EDGE_DETECT_STATUS = (1 << (vector & 0x1F));
} else {
// Not a GPIO interrupt
return;
}
}
void hal_interrupt_configure(int vector, int level, int up)
{
#ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
// Use platform specific handling, if defined
// Note: this macro should do a 'return' for "extended" values of 'vector'
// Normal vectors are handled by code subsequent to the macro call.
HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
#endif
// This function can be used to configure the GPIO interrupts. All
// of these pins can potentially generate an interrupt, but only
// 0..10 are unique. Thus the discontinuity in the numbers.
// Also, if 'level' is true, then both edges are enabled if 'up' is
// true, otherwise they will be disabled.
// Non GPIO sources are ignored.
if ((vector < CYGNUM_HAL_INTERRUPT_GPIO) ||
(vector >= CYGNUM_HAL_INTERRUPT_GPIO11)) {
if (level) {
if (up) {
// Enable both edges
*SA11X0_GPIO_RISING_EDGE_DETECT |= (1 << (vector & 0x1F));
*SA11X0_GPIO_FALLING_EDGE_DETECT |= (1 << (vector & 0x1F));
} else {
// Disable both edges
*SA11X0_GPIO_RISING_EDGE_DETECT &= ~(1 << (vector & 0x1F));
*SA11X0_GPIO_FALLING_EDGE_DETECT &= ~(1 << (vector & 0x1F));
}
} else {
// Only interested in one edge
if (up) {
// Set rising edge detect and clear falling edge detect.
*SA11X0_GPIO_RISING_EDGE_DETECT |= (1 << (vector & 0x1F));
*SA11X0_GPIO_FALLING_EDGE_DETECT &= ~(1 << (vector & 0x1F));
} else {
// Set falling edge detect and clear rising edge detect.
*SA11X0_GPIO_FALLING_EDGE_DETECT |= (1 << (vector & 0x1F));
*SA11X0_GPIO_RISING_EDGE_DETECT &= ~(1 << (vector & 0x1F));
}
}
}
}
void hal_interrupt_set_level(int vector, int level)
{
#ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
// Use platform specific handling, if defined
// Note: this macro should do a 'return' for "extended" values of 'vector'
// Normal vectors are handled by code subsequent to the macro call.
HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
#endif
// Interrupt priorities are not configurable on the SA11X0.
}
/*------------------------------------------------------------------------*/
// These routines are for testing the equivalent efficient macros of the
// same names. They actually inspect the MMap installed and tell the
// truth - including about the validity of the address at all.
cyg_uint32 hal_virt_to_phys_address( cyg_uint32 vaddr )
{
register cyg_uint32 *ttb_base;
cyg_uint32 noise;
register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc;
// Get the TTB register
asm volatile ("mrc p15,0,%0,c2,c0,0;"
"mov %0, %0, lsr #14;" // Lower 14 bits are undefined
"mov %0, %0, asl #14;" // ...so clear them
: "=r"(ttb_base)
:
/*:*/);
noise = vaddr & (SZ_1M - 1);
vaddr /= SZ_1M; // Page size/Entry size is Mb.
desc.word = *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS( ttb_base, vaddr );
// Is this a valid entry that we understand?
if ( ARM_MMU_FIRST_LEVEL_SECTION_ID == desc.section.id )
return noise + desc.section.base_address * SZ_1M;
return 0; // Not available.
}
cyg_uint32 hal_phys_to_virt_address( cyg_uint32 paddr )
{
cyg_uint32 *ttb_base;
cyg_uint32 i, noise;
register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc;
cyg_bool identity_found = false;
// Get the TTB register
asm volatile ("mrc p15,0,%0,c2,c0,0;"
"mov %0, %0, lsr #14;" // Lower 14 bits are undefined
"mov %0, %0, asl #14;" // ...so clear them
: "=r"(ttb_base)
:
/*:*/);
noise = paddr & (SZ_1M - 1);
paddr /= SZ_1M; // Page size/Entry size is Mb.
for ( i = 0; i <= 0xfff; i++ ) {
desc.word = *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS( ttb_base, i );
// Is this a valid entry that we understand?
if ( ARM_MMU_FIRST_LEVEL_SECTION_ID == desc.section.id ) {
if ( paddr == desc.section.base_address ) {
// Then the virtual address is i (in Mb).
if ( i == paddr ) {
// We found a direct map first. Do not report that
// immediately because it may be double mapped to a
// distinct virtual address, which we should return in
// preference. But remember that we saw it.
identity_found = true;
continue;
}
// Otherwise report that we found it:
return noise + i * SZ_1M;
}
}
}
// No non-identity matches were found.
if ( identity_found )
return noise + paddr * SZ_1M;
return 0; // Not available.
}
cyg_uint32 hal_virt_to_uncached_address( cyg_uint32 vaddr )
{
cyg_uint32 *ttb_base;
cyg_uint32 noise, paddr, i;
register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc;
// Get the TTB register
asm volatile ("mrc p15,0,%0,c2,c0,0;"
"mov %0, %0, lsr #14;" // Lower 14 bits are undefined
"mov %0, %0, asl #14;" // ...so clear them
: "=r"(ttb_base)
:
/*:*/);
noise = vaddr & (SZ_1M - 1);
vaddr /= SZ_1M; // Page size/Entry size is Mb.
desc.word = *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS( ttb_base, vaddr );
// Is this a valid entry that we understand?
if ( ARM_MMU_FIRST_LEVEL_SECTION_ID != desc.section.id )
return 0; // Not available.
// Is this very address uncacheable already?
if ( ARM_UNCACHEABLE == desc.section.c )
return noise + vaddr * SZ_1M;
paddr = desc.section.base_address;
// We could look straight at a direct mapped slot for the physical
// address as per convention...
// Now scan through for a virtual address that maps to the same
// physical memory, but uncached.
for ( i = 0; i <= 0xfff; i++ ) {
desc.word = *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS( ttb_base, i );
// Is this a valid entry that we understand?
if ( ARM_MMU_FIRST_LEVEL_SECTION_ID == desc.section.id )
if ( paddr == desc.section.base_address )
// Then the virtual address is i (in Mb).
if ( ARM_UNCACHEABLE == desc.section.c )
// Then this one is not cacheable.
return noise + i * SZ_1M;
}
return 0; // Not available.
}
/*------------------------------------------------------------------------*/
// EOF sa11x0_misc.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -