📄 ixdp2400_misc.c
字号:
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 + -