ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

联德胜微W806移植RTthread-Nano

2021-12-11 11:03:53  阅读:438  来源: 互联网

标签:rt r0 r1 Nano sp RTthread 联德胜微 interrupt uint32


联德胜微W806移植RTthread-Nano

移植前知识点

1、W806芯片基于平头哥E804 CPU内核,该芯片数据手册下载链接:

datasheet/玄铁E804用户手册_v04.pdf · ZH-OuYangLei/W806-RTT-Nano - 码云 - 开源中国 (gitee.com)

2、E804处理器存在两种运行模式: 普通用户模式和超级用户模式,芯片在复位后自动进入超级用户模式,超级用户模式下CPU可以访问所有的寄存器,而用户模式下只能访问少量的寄存器。在对RTT系统移植中,始终保持系统运行在超级用户模式。用户模式对应能访问的寄存器如下图所示:

3、编程模型

寄存器 功能
R0 函数调用时第一个参数
R1 函数调用时第二个参数
R2 函数调用时第三个参数
R3 函数调用时第四个参数
R14 堆栈指针
R15 链接寄存器
EPSR 处理器状态寄存器 PSR的影子寄存器,在进入异常中断时自动保存当前PSR的值
EPC 程序计数器PC的影子寄存器,在进入异常中断时自动保存当前PC的值

堆栈初始化

文件路径: rtthread->libcpu->x804->cpu.c

typedef struct stack_frame
{
	rt_uint32_t epc;
	rt_uint32_t epsr;
	rt_uint32_t r4;
	rt_uint32_t r5;
	rt_uint32_t r6;
	rt_uint32_t r7;
	rt_uint32_t r8;
	rt_uint32_t r9;
	rt_uint32_t r10;
	rt_uint32_t r11;
	
	rt_uint32_t lr; //R15
	rt_uint32_t r16;
	rt_uint32_t r17;
	rt_uint32_t r18;
	rt_uint32_t r19;
	rt_uint32_t r20;
	rt_uint32_t r21;
	rt_uint32_t r22;
	rt_uint32_t r23;
	rt_uint32_t r24;
	rt_uint32_t r25;
	rt_uint32_t r26;
	rt_uint32_t r27;
	rt_uint32_t r28;
	rt_uint32_t r29;
	rt_uint32_t r30;
	rt_uint32_t r31;
	 
	rt_uint32_t fr0;
	rt_uint32_t fr1;
	rt_uint32_t fr2;
	rt_uint32_t fr3;
	rt_uint32_t fr4;
	rt_uint32_t fr5;
	rt_uint32_t fr6;
	rt_uint32_t fr7;
	rt_uint32_t fr8;
	rt_uint32_t fr9;
	rt_uint32_t fr10;
	rt_uint32_t fr11;
	rt_uint32_t fr12;
	rt_uint32_t fr13;
	rt_uint32_t fr14;
	rt_uint32_t fr15;
	
	rt_uint32_t r0;
	rt_uint32_t r1;
	rt_uint32_t r2;
	rt_uint32_t r3;
	rt_uint32_t r12;
	rt_uint32_t r13;
}stack_frame;

rt_uint8_t *rt_hw_stack_init(void       *tentry,
                             void       *parameter,
                             rt_uint8_t *stack_addr,
                             void       *texit)
{
    stack_frame *sf;
    rt_uint8_t         *stk;
    unsigned long       i;

    stk  = stack_addr + sizeof(rt_uint32_t);
    stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
    stk -= sizeof(stack_frame);

    sf = (stack_frame *)stk;

    /* init all register */
    for (i = 0; i < sizeof(stack_frame) / sizeof(rt_uint32_t); i ++)
    {
        ((rt_uint32_t *)sf)[i] = 0xdeadbeef;
    }

    sf->r0  = (unsigned long)parameter; /* r0 : argument */
    sf->r1  = 0x01010101L;                        /* r1 */
    sf->r2  = 0x02020202L;                        /* r2 */
    sf->r3  = 0x03030303L;                        /* r3 */
    sf->r12 = 0x12121212L;                        /* r12 */
	sf->r13 = 0x13131313L;                        /* r12 */
    sf->lr  = (rt_uint32_t)texit;                 /* lr */
    sf->epc = (rt_uint32_t)tentry;                /* entry point, pc */
    sf->epsr = 0x80000140L;                       /* PSR */

    /* return task's current stack address */
    return stk;
}

上下文切换汇编代码编写

文件路径: rtthread->libcpu->x804->contex_x804.s

关闭中断
/*
 * rt_base_t rt_hw_interrupt_disable(void);
 */
.global rt_hw_interrupt_disable   //函数 rt_hw_interrupt_disable
.type   rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
mfcr    r0, CR<0,0>  //读取当前PSR寄存器,函数返回值保存在R0寄存器中
psrclr  ee,ie        //清除ESP中的EE、IE,关闭异常和中断
rts
开启中断
/*
 * void rt_hw_interrupt_enable(rt_base_t psr);
 */
.global rt_hw_interrupt_enable   //函数 rt_hw_interrupt_enable
.type   rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
mtcr    r0, CR<0,0>     //调用函数,实参保存在R0中,该实参为函数rt_hw_interrupt_disable的返回值
rts
第一次切换上下文
/*
 * void rt_hw_context_switch_to(rt_uint32 to);
 * R0 --> to
 */
.global rt_hw_context_switch_to 
.type rt_hw_context_switch_to, %function
rt_hw_context_switch_to:
psrclr  ee,ie

lrw     r1, rt_interrupt_to_thread 
st.w    r0, (r1,0)     

/* set form thread = 0 */
lrw     r1, rt_interrupt_from_thread
lrw     r0, 0
st.w    r0, (r1,0)

lrw     r1, rt_thread_switch_interrupt_flag
lrw     r0, 1
st.w    r0, (r1,0)

/* 初始化TSPEND */
lrw     r0, 0xE000EC10 //设置最低的中断优先级
lrw     r1, 0xff
st.w    r1, (r0,0)

lrw     r0, 0xE000EC0C //清除状态
lrw     r1, 0
st.w    r1, (r0,0)

/*触发tspend中断*/
lrw     r0, 0XE000EC08
bgeni   r1, 0
st.w    r1, (r0,0)

psrset  ee,ie
rts
中断中切换上下文和一般切换上下文
/*
 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
 * r0 --> from
 * r1 --> to
 */
.global rt_hw_context_switch_interrupt
.type   rt_hw_context_switch_interrupt, %function
rt_hw_context_switch_interrupt:

lrw   r2, rt_thread_switch_interrupt_flag
ld.w  r3, (r2,0)
bhz   r3, _to_thread1

lrw   r3, 1
st.w  r3, (r2,0)

lrw   r2, rt_interrupt_from_thread     /* set rt_interrupt_from_thread */
st.w  r0, (r2,0)

_to_thread1:
lrw   r2, rt_interrupt_to_thread       /* set rt_interrupt_to_thread */
st.w  r1, (r2,0)

lrw   r0, 0XE000EC08
bgeni r1, 0
st.w  r1, (r0,0)
rts
挂起中断代码实现

关键点: EPSR、EPC寄存器会在异常中断返回时自动更新到PSR、PC寄存器中

.global tspend_handler
.type   tspend_handler, %function
tspend_handler:
psrclr ee,ie
///压栈 R13-R12,R3-R0
ipush

///判断上下文切换标志
///如果为0,说明没有发生上下文切换调用,则重新开启异常中断,并恢复现场
///如果大于0,说明有发生上下文切换调用,则清除标志,保存from上下文
lrw   r2, rt_thread_switch_interrupt_flag
ld.w  r3, (r2,0)
bez   r3, _enable_ie_ee

lrw   r3, 0
st.w  r3, (r2,0)

///如果不存在from线程,则直接恢复to线程上下文
lrw    r2, rt_interrupt_from_thread
ld.w   r3, (r2,0)
bez    r3, _to_thread3

///保存from线程上下文
subi   sp, sp, 64
fstms  fr0-fr15, (sp)
subi   sp, sp, 68
stm    r15-r31,  (sp)
subi   sp, sp, 32
stm    r4-r11,   (sp)
subi   sp, sp, 8
mfcr   r0, CR<4,0>
mfcr   r1, CR<2,0> 
stm    r0-r1,    (sp)
///更新堆栈地址到thread->sp
st.w   sp, (r3,0)

///恢复to线程上下文
_to_thread3:
lrw    r2, rt_interrupt_to_thread
ld.w   r0,  (r2,0)
ld.w   sp,  (r0,0)

ldm    r0-r1,   (sp)
mtcr   r0,   CR<4,0>
mtcr   r1,   CR<2,0>
addi   sp, sp, 8
ldm    r4-r11,  (sp)
addi   sp, sp, 32
ldm    r15-r31, (sp)
addi   sp, sp, 68
fldms  fr0-fr15,(sp)
addi   sp, sp, 64

///开启异常中断,设置PSR备份寄存器EPSR
_enable_ie_ee:
mfcr   r0, CR<2,0>
bseti  r0, 6 
bseti  r0, 8
mtcr   r0, CR<2,0>

//出栈 R0-R3,R12-R13
ipop
rte

修改Rtthread入口函数

文件路径: platform->arch->xt804->bsp->startup.S

将其中的 jbsr main 替换为 jbsr entry

硬件初始化

在rt_hw_board_init()函数中初始化时钟、GPIO、串口等硬件和相关软件资源,请查看相关软件代码。

编写示例运行结果如下:

图中显示主任务、串口任务、LED闪烁钩子函数已经都成功被调用运行。

整个工程代码请见链接:

W806-RTT-Nano: 基于联德胜微W806芯片移植RTthread-Nano (gitee.com)

标签:rt,r0,r1,Nano,sp,RTthread,联德胜微,interrupt,uint32
来源: https://www.cnblogs.com/BlogsOfLei/p/15674854.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有