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

📄 ixdp2400_misc.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 2 页
字号:
void __attribute__ ((naked)) ixdp2400_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,#0x0\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 <=  2048 << 20,
                "More than 2048MB 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()


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

static cyg_uint32 _period;

void hal_clock_initialize(cyg_uint32 period)
{
    _period = period;

	// I am using timer 1 at 50 MHZ.
	// load the counter
	*(T1_CLD_REG) = period;

	// start the timer
	*(T1_CTL_REG) = T1_CTL_VAL;
}

// This routine is called during a clock interrupt.

void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
{
    // clear the timer interrupt
    *(T1_CLR_REG) = T1_CLR_VAL;
}

// 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)
{
	// read the current counter value
    *pvalue = *(T1_CSR_REG);
}

// reset the system
void ixdp2400_reset()
{
	// only master can reset the system
	if(strap_options_val() & CFG_PCI_BOOT_HOST)
	{
		*(IXP_RESET0_REG) |= RSTALL;
	}
	else
	{
		printf("Only master can reset the system\n");
	}
}

// Delay for some usecs.
void hal_delay_us(cyg_uint32 delay)
{
    cyg_uint32 now, last, diff, ticks, ticks_per_usec;

	ticks_per_usec  = (ext_osc_freq / 2) / 1000000;

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

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

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

	last = now;

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

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

#ifdef ENABLE_INT
void hal_mask_all_int()
{
    unsigned rtmp = 0;

    // disable IRQ
    asm volatile("mrs %0,cpsr\n"
        "orr %0,%0,#0x80\n"
        "msr cpsr,%0\n"
        : "=r"(rtmp) : );
}

void hal_unmask_all_int()
{
    unsigned rtmp = 0;

    // enable IRQ
    asm volatile("mrs %0,cpsr\n"
        "bic %0,%0,#0x80\n"
        "msr cpsr,%0\n"
        : "=r"(rtmp) : );
}
#endif

// This routine is called to respond to a hardware interrupt (IRQ).  It
// should interrogate the hardware and return the IRQ vector number.
int hal_IRQ_handler(void)
{
#ifdef ENABLE_INT
	cyg_uint32 reg_val;
	cyg_uint32 i;

	// check the irq status register
	reg_val = *(IRQ_STATUS_REG);
	if(reg_val == INT_REG_EMPTY)
	{
        return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
    }
	for(i = 0; i < 32; i++)
    {
        // if its a external pci int. then I need to resolve xscale int status reg.
        if((reg_val & (1 << i)) && (i != (CYGNUM_HAL_INTERRUPT_PCI - 1)))
        {
            // return the vector
            return (i + 1);
        }
    }

    // resolve xscale interrupt status register
	reg_val = *(XSCALE_INT_STATUS_REG);
	// silicon team told me that this is raw status. so AND it with enable register.
	reg_val = reg_val & *(XSCALE_INT_ENABLE_REG);
	if(reg_val == INT_REG_EMPTY)
	{
        return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
    }
    for(i = 0; i < 32; i++)
    {
        if(reg_val & (1 << i))
        {
            // add the PCI_INTERRUPT_BASE and return the vector
            return (PCI_INTERRUPT_BASE + i + 1);
        }
    }
#endif
}

//
// Interrupt control
//

void hal_interrupt_mask(int vector)
{
#ifdef ENABLE_INT
	if((vector <= CYGNUM_HAL_ISR_MIN) || (vector > CYGNUM_HAL_ISR_MAX))
	{
		// do nothing
		return;
	}
	if(vector <= PCI_INTERRUPT_BASE)
	{
		// mask the appropriate bit in irq enable register.
		*(IRQ_ENABLE_CLR_REG) = 1 << (vector - 1);
		return;
	}

	// mask the appropriate bit in xscale int enable register
	*(XSCALE_INT_ENABLE_REG) &= ~(1 << (vector - (PCI_INTERRUPT_BASE + 1)));
	return;
#endif
}

// for unmasking dma int. unmask it at both xscale and pci side otherwise it won't work.
void hal_interrupt_unmask(int vector)
{
#ifdef ENABLE_INT
	if((vector <= CYGNUM_HAL_ISR_MIN) || (vector > CYGNUM_HAL_ISR_MAX))
	{
		// do nothing
		return;
	}
	if(vector <= PCI_INTERRUPT_BASE)
	{
		// unmask the appropriate bit in irq enable register.
		*(IRQ_ENABLE_SET_REG) = 1 << (vector - 1);
		return;
	}

	// enable PCI int. in irq enable register
	*(IRQ_ENABLE_SET_REG) = 1 << (CYGNUM_HAL_INTERRUPT_PCI - 1);

	// unmask the appropriate bit in xscale interrupt enable register.
	*(XSCALE_INT_ENABLE_REG) |= 1 << (vector - (PCI_INTERRUPT_BASE + 1));
	return;
#endif
}

void hal_interrupt_acknowledge(int vector)
{
}

void hal_interrupt_configure(int vector, int level, int up)
{
}

void hal_interrupt_set_level(int vector, int level)
{
}

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
/*------------------------------------------------------------------------*/
//  HW Debug support

static inline void set_ibcr0(unsigned x)
{
    asm volatile ("mcr p15,0,%0,c14,c8,0" : : "r"(x) );
}

static inline unsigned get_ibcr0(void)
{
    unsigned x;
    asm volatile ("mrc p15,0,%0,c14,c8,0" : "=r"(x) : );
    return x;
}

static inline void set_ibcr1(unsigned x)
{
    asm volatile ("mcr p15,0,%0,c14,c9,0" : : "r"(x) );
}

static inline unsigned get_ibcr1(void)
{
    unsigned x;
    asm volatile ("mrc p15,0,%0,c14,c9,0" : "=r"(x) : );
    return x;
}

static inline void set_dbr0(unsigned x)
{
    asm volatile ("mcr p15,0,%0,c14,c0,0" : : "r"(x) );
}

static inline unsigned get_dbr0(void)
{
    unsigned x;
    asm volatile ("mrc p15,0,%0,c14,c0,0" : "=r"(x) : );
    return x;
}

static inline void set_dbr1(unsigned x)
{
    asm volatile ("mcr p15,0,%0,c14,c3,0" : : "r"(x) );
}

static inline unsigned get_dbr1(void)
{
    unsigned x;
    asm volatile ("mrc p15,0,%0,c14,c3,0" : "=r"(x) : );
    return x;
}

static inline void set_dbcon(unsigned x)
{
    asm volatile ("mcr p15,0,%0,c14,c4,0" : : "r"(x) );
}

static inline unsigned get_dbcon(void)
{
    unsigned x;
    asm volatile ("mrc p15,0,%0,c14,c4,0" : "=r"(x) : );
    return x;
}

static inline void set_dcsr(unsigned x)
{
	return 0;
}

static inline unsigned get_dcsr(void)
{
	return 0;
}


int cyg_hal_plf_hw_breakpoint(int setflag, void *vaddr, int len)
{
    unsigned int addr = (unsigned)vaddr;

    if (setflag) {
	if (!(get_ibcr0() & 1))
	    set_ibcr0(addr | 1);
	else if (!(get_ibcr1() & 1))
	    set_ibcr1(addr | 1);
	else
	    return -1;
    } else {
	unsigned x = (addr | 1);
	if (get_ibcr0() == x)
	    set_ibcr0(0);
	else if (get_ibcr0() == x)
	    set_ibcr1(0);
	else
	    return -1;
    }
    return 0;
}

int cyg_hal_plf_hw_watchpoint(int setflag, void *vaddr, int len, int type)
{
    unsigned int mask, bit_nr, mode, addr = (unsigned)vaddr;
    unsigned dbcon = get_dbcon();

    mask = 0x80000000;
    bit_nr = 31;
    while (bit_nr) {
	if (len & mask)
	    break;
	bit_nr--;
	mask >>= 1;
    }
    mask = ~(0xffffffff << bit_nr);

    if (setflag) {
	/* set a watchpoint */
	if (type == 2)
	    mode = 1; // break on write
	else if (type == 3)
	    mode = 3; // break on read
	else if (type == 4)
	    mode = 2; // break on any access
	else
	    return 1;

	if (!(dbcon & 3)) {
	    set_dbr0(addr);
	    set_dbr1(mask);
	    set_dbcon(dbcon | mode | 0x100);
	} else
	    return 1;
    } else {
	/* clear a watchpoint */
	if (dbcon & 3)
	    set_dbcon(dbcon & ~3);
	else
	    return 1;
    }
    return 0;
}

// Return indication of whether or not we stopped because of a
// watchpoint or hardware breakpoint. If stopped by a watchpoint,
// also set '*data_addr_p' to the data address which triggered the
// watchpoint.
int cyg_hal_plf_is_stopped_by_hardware(void **data_addr_p)
{
    unsigned fsr, dcsr, dbcon, kind = 0;

    // Check for debug event
    asm volatile ("mrc p15,0,%0,c5,c0,0" : "=r"(fsr) : );
    if ((fsr & 0x200) == 0)
	return HAL_STUB_HW_STOP_NONE;

    // There was a debug event. Check the MOE for details
    dcsr = get_dcsr();
    switch ((dcsr >> 2) & 7) {
      case 1:  // HW breakpoint
      case 3:  // BKPT breakpoint
	return HAL_STUB_HW_STOP_BREAK;
      case 2:  // Watchpoint
	dbcon = get_dbcon();
	if (dbcon & 0x100) {
	    // dbr1 is used as address mask
	    kind = dbcon & 3;
	    *data_addr_p = (void *)get_dbr0();
	}
	if (kind == 1)
	    return HAL_STUB_HW_STOP_WATCH;
	if (kind == 2)
	    return HAL_STUB_HW_STOP_AWATCH;
	if (kind == 3)
	    return HAL_STUB_HW_STOP_RWATCH;
	// should never get here
	break;
    }
    return HAL_STUB_HW_STOP_NONE;
}
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

/*------------------------------------------------------------------------*/
// EOF ixdp2400_misc.c

⌨️ 快捷键说明

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