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 + -
显示快捷键?