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

📄 sa11x0_misc.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 2 页
字号:
}

//
// 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 + -