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

📄 iq80310_misc.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================
//
//      iq80310_misc.c
//
//      HAL misc board support code for XScale IQ80310
//
//==========================================================================
//####COPYRIGHTBEGIN####
//                                                                          
// -------------------------------------------                              
// The contents of this file are subject to the Red Hat eCos Public License 
// Version 1.1 (the "License"); you may not use this file except in         
// compliance with the License.  You may obtain a copy of the License at    
// http://www.redhat.com/                                                   
//                                                                          
// Software distributed under the License is distributed on an "AS IS"      
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
// License for the specific language governing rights and limitations under 
// the License.                                                             
//                                                                          
// The Original Code is eCos - Embedded Configurable Operating System,      
// released September 30, 1998.                                             
//                                                                          
// The Initial Developer of the Original Code is Red Hat.                   
// Portions created by Red Hat are                                          
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
// All Rights Reserved.                                                     
// -------------------------------------------                              
//                                                                          
//####COPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    msalter
// Contributors: msalter
// Date:         2000-10-10
// Purpose:      HAL board support
// Description:  Implementations of HAL board interfaces
//
//####DESCRIPTIONEND####
//
//========================================================================*/

#include <pkgconf/hal.h>
#include <pkgconf/system.h>
#include CYGBLD_HAL_PLATFORM_H
#include CYGHWR_MEMORY_LAYOUT_H

#include <cyg/infra/cyg_type.h>         // base types
#include <cyg/infra/cyg_trac.h>         // tracing macros
#include <cyg/infra/cyg_ass.h>          // assertion macros

#include <cyg/hal/hal_io.h>             // IO macros
#include <cyg/hal/hal_stub.h>           // Stub macros
#include <cyg/hal/hal_if.h>             // calling interface API
#include <cyg/hal/hal_arch.h>           // Register state info
#include <cyg/hal/hal_diag.h>
#include <cyg/hal/hal_intr.h>           // Interrupt names
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/hal_iq80310.h>        // Hardware definitions
#include <cyg/infra/diag.h>             // diag_printf
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED

static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data);

// Some initialization has already been done before we get here.
//
// Set up the interrupt environment.
// Set up the MMU so that we can use caches.
// Enable caches.
// - All done!

void hal_hardware_init(void)
{
    unsigned rtmp = 0;

    // Route INTA-INTD to IRQ pin
    //   The Yavapai manual is incorrect in that a '1' value
    //   routes to the IRQ line, not a '0' value.
    *PIRSR_REG = 0x0f;

    // Disable all interrupt sources:
    *IIMR_REG = 0x7f;
    *OIMR_REG = 0x7f; // don't mask INTD which is really xint3
    *X3MASK_REG = XINT3_TIMER | XINT3_ETHERNET | XINT3_UART_1 | \
	          XINT3_UART_2 | XINT3_PCI_INTD;

    // Let the timer run at a default rate (for delays)
    hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);

    // Set up eCos/ROM interfaces
    hal_if_init();

    // attach some builtin interrupt handlers
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NIRQ, &nirq_ISR, CYGNUM_HAL_INTERRUPT_NIRQ, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NIRQ);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NFIQ, &nfiq_ISR, CYGNUM_HAL_INTERRUPT_NFIQ, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NFIQ);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_MCU_ERR, &nmi_mcu_ISR, CYGNUM_HAL_INTERRUPT_MCU_ERR, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_MCU_ERR);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PATU_ERR, &nmi_patu_ISR, CYGNUM_HAL_INTERRUPT_PATU_ERR, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PATU_ERR);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SATU_ERR, &nmi_satu_ISR, CYGNUM_HAL_INTERRUPT_SATU_ERR, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SATU_ERR);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PBDG_ERR, &nmi_pb_ISR, CYGNUM_HAL_INTERRUPT_PBDG_ERR, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PBDG_ERR);

    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SBDG_ERR, &nmi_sb_ISR, CYGNUM_HAL_INTERRUPT_SBDG_ERR, 0);
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SBDG_ERR);

    // Enable FIQ
#if 0
    asm volatile ("mrs %0,cpsr\n"
		  "bic %0,%0,#0x40\n"
		  "msr cpsr,%0\n"
		  : "=r"(rtmp) : );
#endif
}

#include CYGHWR_MEMORY_LAYOUT_H
void __attribute__ ((naked)) iq80310_program_new_stack(void *func)
{
    asm volatile ("mov    r12,sp\n"
                  "stmdb  sp!, {r4, r12, lr, pc}\n"
                  "sub    r4,r12, #4\n"
                  "mov    r12,#0xa0000000\n"
                  "add    sp,r12,#0x1000000\n"
                  "mov    lr,pc\n"
                  "mov    pc,r0\n"
                  "ldmdb  r4, {r4, sp, pc}\n");
    return;
}

/*------------------------------------------------------------------------*/

//
// Memory layout
//

externC cyg_uint8 *
hal_arm_mem_real_region_top( cyg_uint8 *regionend )
{
    CYG_ASSERT( hal_dram_size > 0, "Didn't detect DRAM size!" );
    CYG_ASSERT( hal_dram_size <=  512<<20,
                "More than 512MB reported - that can't be right" );

    // is it the "normal" end of the DRAM region? If so, it should be
    // replaced by the real size
    if ( regionend ==
         ((cyg_uint8 *)CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE) ) {
        regionend = (cyg_uint8 *)CYGMEM_REGION_ram + hal_dram_size;
    }
    return regionend;
} // hal_arm_mem_real_region_top()


// -------------------------------------------------------------------------

// Clock can come from the PMU or from an external timer.
// The external timer is the preferred choice.

#if CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL

// Proper version that uses the clock counter in the PMU to do proper
// interrupts that require acknowledgement and all that good stuff.

static cyg_uint32 hal_clock_init_period; // The START value, it counts up

void hal_clock_initialize(cyg_uint32 period)
{
    // event types both zero; clear all 3 interrupts;
    // disable all 3 counter interrupts;
    // CCNT counts every processor cycle; reset all counters;
    // enable PMU.
    register cyg_uint32 init = 0x00000707;
    asm volatile (
        "mcr      p14,0,%0,c0,c0,0;" // write into PMNC
        :
        : "r"(init)
        /*:*/
        );
    // the CCNT in the PMU counts *up* then interrupts at overflow
    // ie. at 0x1_0000_0000 as it were.
    // So init to 0xffffffff - period + 1 to get the right answer.
    period = (~period) + 1;
    hal_clock_init_period = period;
    hal_clock_reset( 0, 0 );
}

// This routine is called during a clock interrupt.
// (before acknowledging the interrupt)
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
{
    asm volatile (
        "mrc      p14,0,r0,c1,c0,0;" // read from CCNT - how long since OVFL
        "add      %0, %0, r0;"       // synchronize with previous overflow
        "mcr      p14,0,%0,c1,c0,0;" // write into CCNT
        :
        : "r"(hal_clock_init_period)
        : "r0"
        );
}

// Read the current value of the clock, returning the number of hardware
// "ticks" that have occurred (i.e. how far away the current value is from
// the start)

void hal_clock_read(cyg_uint32 *pvalue)
{
    register cyg_uint32 now;
    asm volatile (
        "mrc      p14,0,%0,c1,c0,0;" // read from CCNT
        : "=r"(now)
        :
        /*:*/
        );
    *pvalue = now - hal_clock_init_period;
}

// Delay for some usecs.
void hal_delay_us(cyg_uint32 delay)
{
  int i;
  // the loop is going to take 3 ticks.  At 600 MHz, to give uS, multiply
  // by 600/3 = 200. No volatile is needed on i; gcc recognizes delay
  // loops and does NOT elide them.
  for ( i = 200 * delay; i ; i--)
    ;
}

#else // external timer

static cyg_uint32 _period;

void hal_clock_initialize(cyg_uint32 period)
{
    _period = period;

    // disable timer
    EXT_TIMER_INT_DISAB();
    EXT_TIMER_CNT_DISAB();

    *TIMER_LA0_REG_ADDR = period;
    *TIMER_LA1_REG_ADDR = period >> 8;
    *TIMER_LA2_REG_ADDR = period >> 16;

    EXT_TIMER_INT_ENAB();
    EXT_TIMER_CNT_ENAB();
}

// This routine is called during a clock interrupt.

void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
{
    // to clear the timer interrupt, clear the timer interrupt
    // enable, then re-set the int. enable bit
    EXT_TIMER_INT_DISAB();
    EXT_TIMER_INT_ENAB();
}

// Read the current value of the clock, returning the number of hardware
// "ticks" that have occurred (i.e. how far away the current value is from
// the start)

void hal_clock_read(cyg_uint32 *pvalue)
{
    cyg_uint8  cnt0, cnt1, cnt2, cnt3;
    cyg_uint32 timer_val;;

    // first read latches the count
    // Actually, it looks like there is a hardware problem where
    // invalid counts get latched. This do while loop appears
    // to get around the problem.
    do {
	cnt0 = *TIMER_LA0_REG_ADDR & TIMER_COUNT_MASK;
    } while (cnt0 == 0);
    cnt1 = *TIMER_LA1_REG_ADDR & TIMER_COUNT_MASK;
    cnt2 = *TIMER_LA2_REG_ADDR & TIMER_COUNT_MASK;
    cnt3 = *TIMER_LA3_REG_ADDR & 0xf;	/* only 4 bits in most sig. */

    /* now build up the count value */
    timer_val  =  ((cnt0 & 0x40) >> 1) | (cnt0 & 0x1f);
    timer_val |= (((cnt1 & 0x40) >> 1) | (cnt1 & 0x1f)) << 6;
    timer_val |= (((cnt2 & 0x40) >> 1) | (cnt2 & 0x1f)) << 12;
    timer_val |= cnt3 << 18;

    *pvalue = timer_val;
}

// Delay for some usecs.
void hal_delay_us(cyg_uint32 delay)
{
#define _CNT_MASK 0x3fffff
#define _TICKS_PER_USEC (EXT_TIMER_CLK_FREQ / 1000000)
    cyg_uint32 now, last, diff, ticks;

    hal_clock_read(&last);
    diff = ticks = 0;

    while (delay > ticks) {
	hal_clock_read(&now);

	if (now < last)
	    diff += ((_period - last) + now);
	else
	    diff += (now - last);

	last = now;

	if (diff >= _TICKS_PER_USEC) {
	    ticks += (diff / _TICKS_PER_USEC);
	    diff %= _TICKS_PER_USEC;
	}
    }
}

#endif

// -------------------------------------------------------------------------

typedef cyg_uint32 cyg_ISR(cyg_uint32 vector, CYG_ADDRWORD data);

extern void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );

static inline cyg_uint32
hal_call_isr (cyg_uint32 vector)
{
    cyg_ISR *isr;
    CYG_ADDRWORD data;
    cyg_uint32 isr_ret;

    isr = (cyg_ISR*) hal_interrupt_handlers[vector];
    data = hal_interrupt_data[vector];

    isr_ret = (*isr) (vector, data);

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
    if (isr_ret & CYG_ISR_CALL_DSR) {
        cyg_interrupt_post_dsr (hal_interrupt_objects[vector]);
    }
#endif

    return isr_ret & ~CYG_ISR_CALL_DSR;
}

void _scrub_ecc(unsigned p)
{
    asm volatile ("ldrb r4, [%0]\n"
		  "strb r4, [%0]\n" : : "r"(p) );
}

static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
    cyg_uint32 eccr_reg;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -