visitor83
visitor83

注册于 9 years ago

回答
0
文章
0
关注者
0

确实在vector.S中hal_default_exception_vsr 有去call hal_deliver_exception, 初始化将2~15中断向量都指向了hal_default_exception_vsr, 压入R1=exception state type, R2= vector number, R3=basepri, hal_default_exception_vsr参数为数据寄存器r0~r10, r11~r15, cpsr, vector, svc_lr, svc_sp,应该跟压入的参数顺序一致

_hal_registers = regs // _hal_registers 在packages/hal/common/current/src/hal_stub.c中定义 ,接下来执行__handle_exception(void)中要处理真正的stub

在packages/hal/cortexm/arch/current/src/hal_misc.c中hal_reset_vsr(void)-->


#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
// Enable DebugMonitor exceptions. This is needed to enable single
// step. This only has an effect if no exteranl JTAG device is attach
{
CYG_ADDRESS base = CYGARC_REG_DEBUG_BASE;
cyg_uint32 demcr;
HAL_READ_UINT32(base + CYGARC_REG_DEBUG_DEMCR, demcr);
demcr |= CYGARC_REG_DEBUG_DEMCR_MON_EN;
HAL_WRITE_UINT32(base + CYGARC_REG_DEBUG_DEMCR, demcr);
}

看代码里_DEMCR这个宏是另一套stub实现,具体在看。

initialize_stub() : package/hal/common/current/src/generic-stub.c 初始化
1) install the standard set of trap handlers for the stub
在pakcages/hal/cortexm/stm32/var/current/include/plf_stub.h中指定
HAL_STUB_PLATFROM_INTERRUPTIBLE = 0不允许中断发生,其他中断与非stub使能状态一样。

2) 安装stub的设备例如串口 packages/hal/cortexm/stm32/var/current/src/hal_diag.c-->cyg_hal_plf_comms_int(void),然后发出去个'+' 回应。

粗略读了下ecos代码,下来在读hal_deliver_exception

感谢回复,
(4)while (1)
{
if (rt_mb_recv(&eth_tx_thread_mb, (rt_uint32_t*)&msg, RT_WAITING_FOREVER) == RT_EOK)
{
struct eth_device* enetif;

RT_ASSERT(msg->netif != RT_NULL);
RT_ASSERT(msg->buf != RT_NULL);

enetif = (struct eth_device*)msg->netif->state;
if (enetif != RT_NULL)
{
/* call driver's interface */
if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)
{
rt_kprintf("transmit eth packet failed\n");
}
}

/* send ack */
rt_sem_release(&(enetif->tx_ack));
}
}

这个没有 break ?

忘了,感谢bernard的指教。上述有什么不对,还请各位指点!

明白了!
线程第一次运行,它的默认上下文环境就是开启中断的,那么当这个线程被恢复时,那么系统中断不就立刻被打开了么
<<问题的关键是:
1。每一个进程都有自己的空间互不干扰。 进程被os恢复时,等于从进程的第一条指令开始执行,与其他什么乱七八糟的没什么关系。
2。 ARM Mode 的切换, rtthread 启动后一直是处于svc mode下,CPSR的F, I bit一直都是1,所以arm920t core的irq, fiq全部都是disable的。即使Interrupt register打开也没有用。
3。 第一次切换进程时的恢复上下文的设置。

	stk 	 = (rt_uint32_t*)stack_addr;
*(stk) = (rt_uint32_t)tentry; /* entry point */
*(--stk) = (rt_uint32_t)texit; /* lr */
*(--stk) = 0; /* r12 */
*(--stk) = 0; /* r11 */
*(--stk) = 0; /* r10 */
*(--stk) = 0; /* r9 */
*(--stk) = 0; /* r8 */
*(--stk) = 0; /* r7 */
*(--stk) = 0; /* r6 */
*(--stk) = 0; /* r5 */
*(--stk) = 0; /* r4 */
*(--stk) = 0; /* r3 */
*(--stk) = 0; /* r2 */
*(--stk) = 0; /* r1 */
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
*(--stk) = SVCMODE; /* cpsr */
*(--stk) = SVCMODE; /* spsr */

下面的SVCMODE = 0x13,那么其实CPSR register中F, I bit 已经被打开了,所以说进程一进去就可以执行。

楼主正解,代码里也是这样的,打开IRQ_DEBUG,一直到rt_system_scheduler_start();
才有中断的debug输出,所以很困惑。

第一个进程是idle

void rt_thread_idle_init()
{
/* init thread */
rt_thread_init(&idle,
"tidle",
rt_thread_idle_entry, RT_NULL,
&rt_thread_stack[0], sizeof(rt_thread_stack),
RT_THREAD_PRIORITY_MAX - 1, 32);

/* startup */
rt_thread_startup(&idle);
}

然后进入到
rt_system_scheduler_start();先查找优先级最高的进程,idle,在进入上下文切换的汇编代码。
/*
* void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer

ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
ldmfd sp!, {r4} @ pop new task cpsr
msr cpsr_cxsf, r4

ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc

将保存的新进程的stack pop出去,并将pc指针定位到新的进程开始执行,你知道在那里开启中断,
不胜感谢,计划rtthread移植到新的平台下,所以拿2440先study下整个流程,谢谢。

当然知道,第一个线程不起来要tick没什么必要,但是,没有找到开启中断的代码
在rtthread-0.4.0,所以才困惑!你知道那段代码开启?

我没说清楚,问题是,PWM Timer4中断开启,并启动了,但直到rt_system_scheduler_start()
中断才可以进到中断vector_irq中,这是为什么。请高手指点,谢谢。

OK , debug也是如此
(gdb) x/60x 0x00000000
0x0: 0x3000f9c0 0xe59ff014 0xe59ff014 0xe59ff014
0x10: 0xe59ff014 0xe59ff014 0xe59ff014 0xe59ff014
0x20: 0x30000120 0x30000160 0x30000180 0x300001a0
0x30: 0x300001e0 0x300001e4 0x30000220 0xdeadbeef
0x40: 0x30000000 0x30000000 0x00000b00 0x30200000
0x50: 0x302040bc 0x30202748 0x30201f48 0x30202148
0x60: 0x30202348 0x30077804 0xe10f0000 0xe3c0001f
0x70: 0xe3800013 0xe129f000 0xe3a00453 0xe3a01000
0x80: 0xe5801000 0xe59f1270 0xe3e00000 0xe5810000
0x90: 0xe59f1268 0xe59f0268 0xe5810000 0xe59f0060
0xa0: 0xe3a01000 0xe2802020 0xe8b007f8 0xe8a107f8
0xb0: 0xe1500002 0xdafffffb 0xeb00007c 0xe3a00000
0xc0: 0xe59f1240 0xe59f2240 0xe1510002 0x34810004
0xd0: 0x3afffffc 0xe59f0234 0xe59f1234 0xe1500001
0xe0: 0x0a000005 0xe4902004 0xe92d0003 0xe1a0e00f
(gdb) x/60x 0x30000120
0x30000120 : 0xe24dd048 0xe88d1fff 0xe28d803c 0xe9486000
0x30000130 : 0xe588e000 0xe14f6000 0xe5886004 0xe5880008
0x30000140 : 0xe1a0000d 0xeb003981 0xe1a00000 0xe1a00000
0x30000150 : 0xe1a00000 0xe1a00000 0xe1a00000 0xe1a00000
0x30000160 : 0xeb00398f 0xe1a00000 0xe1a00000 0xe1a00000
0x30000170 : 0xe1a00000 0xe1a00000 0xe1a00000 0xe1a00000
0x30000180 : 0xeb003994 0xe1a00000 0xe1a00000 0xe1a00000
0x30000190 : 0xe1a00000 0xe1a00000 0xe1a00000 0xe1a00000
0x300001a0 : 0xe24dd048 0xe88d1fff 0xe28d803c 0xe9486000
0x300001b0 : 0xe588e000 0xe14f6000 0xe5886004 0xe5880008
0x300001c0 : 0xe1a0000d 0xeb003998 0xe1a00000 0xe1a00000
0x300001d0 : 0xe1a00000 0xe1a00000 0xe1a00000 0xe1a00000
0x300001e0 : 0xeb0039a6 0xe92d5fff 0xeb001dc8 0xeb0039b0
0x300001f0 : 0xeb001dd8 0xe59f011c 0xe5901000 0xe3510001
0x30000200 : 0x0a00000a 0xe8bd5fff 0xe25ef004 0xe1a00000
那么实际上可以说start_gcc.S是没有用到了

以上问题还是困扰着阿,首先start_gcc.S
/* set interrupt vector */
ldr r0, _load_address
mov r1, #0x0 /* target address */
add r2, r0, #0x20 /* size, 32bytes */

copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
中是将0x3000000~ 0x30000000+0x20的内容copy到0x00000000,但是我调试发现0x0000000的地址上全是0x00000000.
版主有说通过MMU去重新定向,意思是说在mmu_init 之后将0x00000000的虚拟地址访问时通过MMU的重新定向到0x3000000
mmu_setmtt(0x00000000,0x03f00000,(int)0x30000000,RW_CB); //bank0
那么实际上start_gcc.S中的copy是作工作了马?
很糊涂。谁能清晰的解释下马,非常感谢。

自问自答,根据arm920t techinical ref manual
上述代码是使用的Section Descriptor:
A section descriptor provides the base addresss of a 1MB block of memory,
所以rt-thread在arm920t下应该是没有开启page功能。
但为什么是两个bank 0还是不知道哦

void mmu_setmtt(int vaddrStart,int vaddrEnd,int paddrStart,int attr)
{
volatile rt_uint32_t *pTT;
volatile int i,nSec;
pTT=(rt_uint32_t *)_MMUTT_STARTADDRESS+(vaddrStart>>20);
nSec=(vaddrEnd>>20)-(vaddrStart>>20);
for(i=0;i<=nSec;i++)
{
*pTT = attr |(((paddrStart>>20)+i)<<20);
pTT++;
}
}
应该是建立Address Translation Table,建立的内容如下:
//mmu_setmtt(int vaddrStart,int vaddrEnd,int paddrStart,int attr);
mmu_setmtt(0x00000000,0x07f00000,0x00000000,RW_CNB); //bank0
mmu_setmtt(0x00000000,0x03f00000,(int)0x30000000,RW_CB); //bank0
怎么会有两个bank0, 另外为什么没有页的大小之类的定义?RT-Thread是如何实现内存管理的呢?

意思是说内存访问事控制器通过MMU 将0x0000,0000 (virtual Memory)<-> 0x3000,0000(physical Memory)那里?

发布
问题