sa11x0_misc.c
来自「eCos操作系统源码」· C语言 代码 · 共 565 行 · 第 1/2 页
C
565 行
if ( sources & 0xff0000 ) index = 16; else if ( sources & 0xff00 ) index = 8; else if ( sources & 0xff ) index = 0; else // if ( sources & 0xff000000 ) index = 24; do { if ( (1 << index) & sources ) { if (index == CYGNUM_HAL_INTERRUPT_GPIO) { // Special case of GPIO cascade. Search for lowest set bit sources = *SA11X0_GPIO_EDGE_DETECT_STATUS & 0x0FFFF800; index = 11; do { if (sources & (1 << index)) { index += 32; break; } index++; } while (index < 28); } return index; } index++; } while ( index & 7 ); return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!}//// 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 + =
减小字号Ctrl + -
显示快捷键?