查看: 921|回复: 1

RT-Thread移植到织女星开发板及功能测试

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32035
    最后登录
    2024-4-26
    发表于 2019-12-5 09:40:12 | 显示全部楼层 |阅读模式
    上个学期天津大学的吕卫老师,在他《微处理器系统》课程的实验环节上,让研究生们使用织女星开发板做了一些项目。


    本文是其中一份工作,由国际工程师学院,电子与通信工程的徐扬扬和张千依同学共同完成的实验报告,呈现给大家作为参考。
    9.png
    织女星开发板简介


    织女星开发板是一款基于无线MCU RV32M1的RISC-V的评估开发板。
    RV32M1集成了可工作在2.36GHz到2.48GHz频率范围,支持FSK/GFSK和O-QPSK调制的无线收发器。
    RV32M1是一颗异构四核MCU芯片,包括一个RISC-V RI5CY核、一个RISC-V ZERO_RISCY核、一个Arm Cortex-M4F核和一个Cortex-M0+核。
    织女星开发板包括主芯片RV32M1、32MHz参考晶振、RF射频电路(包括PCB 天线)、32-Mbit的外部SPI串行Flash和支持标准的Freedom板接口。
    www.open-isa.cn提供支持RV32M1的RISC-V核的GNU GCC工具链、SDK软件开发包和其它相关文档和软件的下载链接。
    10.png
    RT-Thread移植步骤


    1首先下载RT-Thread官方发布的最新版本并解压到某个目录。


    2安装env工具 Env 是 RT-Thread 推出的开发辅助工具,针对基于 RT-Thread 操作系统的项目工程,提供编译构建环境、图形化系统配置及软件包管理功能。其内置的 menuconfig 提供了简单易用的配置剪裁工具,可对内核、组件和软件包进行自由裁剪,使系统以搭积木的方式进行构建。


    3安装并使用riscv-embed-gcc工具链(添加环境变量)。


    4使用env工具编译项目

    a)首先进入到工程目录下(bsp目录下找到对应的板级支持包)

    b)设置使用riscv-embed-gcc工具链(这是设置使用自己的GCC工具链)


    在我的电脑上就是使用如下命令:


    set RTT_EXEC_PATH=D:\GNU MCU Eclipse\RISC-V Embedded GCC\8.2.0-2.2-20190521-0004\bin

    c)调试程序
    在官方包中,编译时遇到错误,修改项目文件中D:\rt-thread-master\include\libc\libc_signal.h文件,将其中的sigval, sigevent, siginfo定义注释掉(两处定义有重复,需要注释掉其中一个文件中的定义)

    d)在env工具命令行输入scons进行编译,编译成功后产生rtthread.elf文件,即是可以烧进板子中的文件。


    5使用openocd+gdb连接开发板并进行调试

    a)首先连接板子和电脑

    b)打开一个cmd窗口,使用如下指令连接到目标板
    openocd -f  F:\MCU\kaifabanziliao\Release\rv32m1_sdk_riscv\rv32m1_sdk_riscv\boards\rv32m1_vega\rv32m1_ri5cy.cfg

    c)打开一个新的cmd,进入到之前生成的.elf文件所在目录

    d)输入如下指令来运行gdb调试
    riscv32-unknown-elf-gdb rtthread.elf

    e)输入如下指令来连接gdb到openocd
    target remote localhost:3333

    f)输入load命令将二进制文件加载到flash当中去

    g)打开设备管理器找到串口号如COM3,打开串口调试程序putty将connection type选择成serial,将波特率设置为115200

    h)输入monitor reset重启一下,就能看到RT-Thread启动的logal信息,如下:
    11.png


    i)输入help,可以看到该系统提供的各种指令
    12.png
    j)通过env工具可以对软件包进行管理,根据需求进行增减。(RT-Thread官方提供的工具,可以很方便的对系统进行裁剪和应用的添加,更多使用教程参见

    利用板上LED和按键开发程序


    在移植RT-Thread系统后,利用开发板上的LED和按键实现按键对LED开关及颜色的控制。
    一、LED及按键使用简介
    LED的亮灭控制
    织女星开发板上有一个RGB三色LED灯,可以供应用程序作为指示信息使用。还提供了一个红色的LED指示灯(D2),可以用来作为一般的状态指示灯。
    下图为这些LED电路图:
    13.png
    LED由VTGT_MCU供电,灯的开关是由Q1和Q2控制。通过Q1和Q2,即使GPIO的电压小于VTGT_MCU,LED灯也可以正常被控制。RGB三色LED灯中的蓝色灯和绿色灯,如果VTGT_MCU供电电压太小,则它们有可能无法点亮。
    首先定义LED的管脚,通过查阅开发资料,不同的颜色对应的管脚分别为:
    #define LED_BLUE 23
    #define LED_GREEN 24
    #define LED_RED 25
    然后通过RT-Thread系统封装的函数rt_pin_mode()将管脚设置为输出模式:
    // 设置管脚为输出模式
    rt_pin_mode(LED_BLUE, PIN_MODE_OUTPUT);
    接下来通过向管脚写入电平值来控制LED的亮灭。
    // 输出低电平,红灯亮
    rt_pin_write(LED_RED, PIN_HIGH);


    用户按键控制
    织女星开发板提供了四个按钮可以完成某些作为人机互动(HMI)操作。开关按钮的电路图如下所示:
    14.png
    SW2提供了一个外部上拉电阻,然后连接到RV32M1的NMI引脚。这使得可以使用这个按钮作为NMI信号或者设备唤醒源,ROM bootloader的启动选项源,或者作为一个通用的输入中断源。


    SW3、SW4和SW5可以作为普通输入信号,可以作为中断或唤醒源。使用这些信号时,必须使能这些引脚内部的上拉电阻。
    开关的控制原理同LED类似,也是通过:定义管脚,设置管脚模式,检测电平,来判断按键是否按下。

    二、程序实现


    程序1:LED闪烁程序
    首先定义线程体:
    15.png
    在线程体内定义好要进行的操作,比如我在线程体内定义了LED的开关,实现闪烁。
    其次通过rt_thread_create()函数来创建线程,并设置好各项参数,
    16.png
    最后将命令导出到控制台,使用
    17.png
    程序2:按键控制
    按键控制的原理类似于LED,在线程体内,首先将按键的管脚设置为上拉输入,然后通过另外一个函数rt_pin_read()来检测电平变化,若检测到低电平则按键按下,考虑到人手按键的持续时间,检测到低电平后延时500ms,此时通过向控制台打印信息说明成功,说明按键可以使用了。
    18.png
    程序3:线程间通信
    创建两个线程,分别为按键线程和LED线程声明一个信号量,在按键线程中检测到按键按下后,通过信号量告知LED线程点亮LED,从而实现按键控制LED的亮灭和颜色变化。
    19.png
    代码


    程序1:
    #include <rtthread.h>
    #include <rtdevice.h>
    #include <stdlib.h>
    #define LED_BLUE 23
    #define LED_GREEN 24
    #define LED_RED 25
    //static int pin_num;
    static void led_thread_entry(void* parameter)
    {
            //设置管脚为输出模式
            rt_pin_mode(LED_BLUE, PIN_MODE_OUTPUT);
            //设置管脚为输出模式
            rt_pin_mode(LED_GREEN, PIN_MODE_OUTPUT);
            //设置管脚为输出模式
            rt_pin_mode(LED_RED, PIN_MODE_OUTPUT);
            while (1)
            {
                    //红色
                    //输出低电平,红灯 亮
                    rt_pin_write(LED_RED, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,红灯 灭
                    rt_pin_write(LED_RED, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));


                   
                    //绿色
                    //输出低电平,绿灯 亮
                    rt_pin_write(LED_GREEN, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,绿灯 灭
                    rt_pin_write(LED_GREEN, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));


                   
                    //蓝色
                    //输出低电平,蓝灯 亮
                    rt_pin_write(LED_BLUE, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,蓝灯 灭
                    rt_pin_write(LED_BLUE, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));




                    //黄色=红+绿
                    //输出低电平,红灯 亮
                    rt_pin_write(LED_RED, PIN_HIGH);
                    //输出低电平,绿灯 亮
                    rt_pin_write(LED_GREEN, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,红灯 灭
                    rt_pin_write(LED_RED, PIN_LOW);
                    //输出高电平,绿灯 灭
                    rt_pin_write(LED_GREEN, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));




                    //青色=蓝+绿
                    //输出低电平,蓝灯 亮
                    rt_pin_write(LED_BLUE, PIN_HIGH);
                    //输出低电平,绿灯 亮
                    rt_pin_write(LED_GREEN, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,蓝灯 灭
                    rt_pin_write(LED_BLUE, PIN_LOW);
                    //输出高电平,绿灯 灭
                    rt_pin_write(LED_GREEN, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));




                    //品红色=蓝+红
                    //输出低电平,蓝灯 亮
                    rt_pin_write(LED_BLUE, PIN_HIGH);
                    //输出低电平,红灯 亮
                    rt_pin_write(LED_RED, PIN_HIGH);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
                    //输出高电平,蓝灯 灭
                    rt_pin_write(LED_BLUE, PIN_LOW);
                    //输出高电平,红灯 灭
                    rt_pin_write(LED_RED, PIN_LOW);
                    //挂起 500ms
                    rt_thread_delay(rt_tick_from_millisecond(500));
            }
    }


    static int led_sample(void* parameter)
    {
            rt_thread_t tid;//线程句柄
            rt_err_t ret = RT_EOK;
            /*创建led线程*/
            tid = rt_thread_create("led",
                                                      led_thread_entry,
                                                      RT_NULL,
                                                      1024,
                                                      3,
                                                      10);
            /*创建成功则启动线程*/
            if (tid != RT_NULL)
            {
                    rt_thread_startup(tid);
            }
            else
            {
                    ret=RT_ERROR;
            }
            return ret;
    }
    MSH_CMD_EXPORT(led_sample, led sample);




    程序2:


    #include <rtthread.h>
    #include <rtdevice.h>
    #include <stdlib.h>
    #define LED_BLUE 23
    #define LED_GREEN 24
    #define LED_RED 25
    #define LED_YELLOW 26
    #define LED_CHING 27
    #define LED_MAGENTA 28
    #define LED_WHITE 29
    #define KEY_PIN 1


    static void key_thread_entry(void* parameter)
    {
            //SW2设置上拉输入
            rt_pin_mode(KEY_PIN, PIN_MODE_INPUT_PULLUP);
            //设置LED输入
            rt_pin_mode(LED_BLUE, PIN_MODE_OUTPUT);
            rt_pin_mode(LED_GREEN, PIN_MODE_OUTPUT);
            rt_pin_mode(LED_RED, PIN_MODE_OUTPUT);
            //定义FLAG用于切换按键效果
            static rt_uint8_t FLAG = PIN_HIGH;
            static rt_uint8_t color = 23;
            static int count = 0;
            while (1)
            {
                    if (rt_pin_read(KEY_PIN) == PIN_LOW)
                    {
                            rt_thread_mdelay(300);
                            rt_kprintf("检测到按键按下\n");
                            count = count + 1;
                            switch(color){
                                    case LED_BLUE:rt_pin_write(LED_BLUE, FLAG);break;
                                    case LED_GREEN:rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_RED:rt_pin_write(LED_RED, FLAG);break;
                                    case LED_YELLOW:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_CHING:rt_pin_write(LED_BLUE, FLAG),rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_MAGENTA:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_BLUE, FLAG);break;
                                    case LED_WHITE:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_GREEN, FLAG),rt_pin_write(LED_BLUE,FLAG);break;
                                    //default:rt_pin_write(LED_BLUE, FLAG);
                            }
                            if (count%2 == 0)//每按两次实现一种颜色的亮灭,之后换一种颜色
                            {
                                    color = color + 1;
                                    if (color > 29)
                                    {
                                            color = 23;
                                    }
                            }


                            //改变下一次按键的作用
                            if(FLAG == PIN_HIGH)
                            {
                                    rt_kprintf("亮灯!\n");
                                    FLAG = PIN_LOW;
                            }else
                            {
                                    rt_kprintf("灭灯!\n");
                                    FLAG = PIN_HIGH;
                            }
                            rt_kprintf("********************************\n");
                    }
            }
            //挂起 10ms
            //rt_thread_delay(rt_tick_from_millisecond(10));
    }
    static int key_sample(void* parameter)
    {
            rt_thread_t tid;//线程句柄
            rt_err_t ret = RT_EOK;
            /*创建led线程*/
            tid = rt_thread_create("key",
                                                      key_thread_entry,
                                                      RT_NULL,
                                                      1024,
                                                      3,
                                                      10);
            /*创建成功则启动线程*/
            if (tid != RT_NULL)
            {
                    rt_thread_startup(tid);
            }
            else
            {
                    ret=RT_ERROR;
            }
            return ret;
    }
    MSH_CMD_EXPORT(key_sample, key sample);




    程序3:


    #include <rtthread.h>
    #include <rtdevice.h>
    #include <stdlib.h>
    #define LED_BLUE 23
    #define LED_GREEN 24
    #define LED_RED 25
    #define LED_YELLOW 26
    #define LED_CHING 27
    #define LED_MAGENTA 28
    #define LED_WHITE 29
    #define KEY_PIN 1
    #define THREAD_PRIORITY 25
    #define THREAD_TIMESLICE 5


    /* 指向信号量的指针 */
    static rt_sem_t dynamic_sem = RT_NULL;
    //定义计数决定开关
    static int count = 0;
    //定义起始颜色为蓝色
    static rt_uint8_t color = 23;




    ALIGN(RT_ALIGN_SIZE)
    static char thread1_stack[1024];
    static struct rt_thread thread1;
    static void rt_thread1_entry(void *parameter)
    {
            //SW2设置上拉输入
            rt_pin_mode(KEY_PIN, PIN_MODE_INPUT_PULLUP);


            while (1)
            {
                    if (rt_pin_read(KEY_PIN) == PIN_LOW)
                    {
                            //延时
                            rt_thread_mdelay(300);
                            rt_kprintf("按键按下,释放信号量.\n");
                            //释放信号量
                            rt_sem_release(dynamic_sem);
                    }
            }
    }


    ALIGN(RT_ALIGN_SIZE)
    static char thread2_stack[1024];
    static struct rt_thread thread2;
    static void rt_thread2_entry(void *parameter)
    {
            //定义电平标志
            static rt_uint8_t FLAG = PIN_HIGH;
            static rt_err_t result;
            //设置LED输入模式
            rt_pin_mode(LED_BLUE, PIN_MODE_OUTPUT);
            rt_pin_mode(LED_GREEN, PIN_MODE_OUTPUT);
            rt_pin_mode(LED_RED, PIN_MODE_OUTPUT);
            while (1)
            {
            /* 永久方式等待信号量,获取到信号量,则执行操作 */
                    result = rt_sem_take(dynamic_sem, RT_WAITING_FOREVER);
                    if (result != RT_EOK)
                    {
                            rt_kprintf("thread2 take a dynamic semaphore, failed!.\n");
                            rt_sem_delete(dynamic_sem);
                            return;
                    }
                    else
                    {
                            rt_kprintf("LED线程拿到信号量.做出操作\n");
                            switch(color){
                                    case LED_BLUE:rt_pin_write(LED_BLUE, FLAG);break;
                                    case LED_GREEN:rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_RED:rt_pin_write(LED_RED, FLAG);break;
                                    case LED_YELLOW:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_CHING:rt_pin_write(LED_BLUE, FLAG),rt_pin_write(LED_GREEN, FLAG);break;
                                    case LED_MAGENTA:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_BLUE, FLAG);break;
                                    case LED_WHITE:rt_pin_write(LED_RED, FLAG),rt_pin_write(LED_GREEN, FLAG),rt_pin_write(LED_BLUE,FLAG);break;
                                    //default:rt_pin_write(LED_BLUE, FLAG);
                    }


                            count = count + 1;
                            if (count%2 == 0)//每按两次实现一种颜色的亮灭,之后换一种颜色
                            {
                                    color = color + 1;
                                    if (color > 29)
                                    {
                                            color = 23;
                                    }
                            }


                            //改变下一次按键的作用
                            if(FLAG == PIN_HIGH)
                            {
                                    rt_kprintf("亮灯!\n");
                                    FLAG = PIN_LOW;
                            }else
                            {
                                    rt_kprintf("灭灯!\n");
                                    FLAG = PIN_HIGH;
                            }
                            rt_kprintf("********************************\n");
                    }
            }
    }


    /* 信号量示例的初始化 */
    int semaphore_sample()
    {
            /* 创建一个动态信号量,初始值是0 */
            dynamic_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
            if (dynamic_sem == RT_NULL)
            {
                    rt_kprintf("create dynamic semaphore failed.\n");
                    return -1;
            }
            else
            {
                    rt_kprintf("create done. dynamic semaphore value = 0.\n");
            }


            rt_thread_init(&thread1,
                                            "thread1",
                                            rt_thread1_entry,
                                            RT_NULL,
                                            &thread1_stack[0],
                                            sizeof(thread1_stack),
                                            THREAD_PRIORITY, THREAD_TIMESLICE);
            rt_thread_startup(&thread1);


            rt_thread_init(&thread2,
                                            "thread2",
                                            rt_thread2_entry,
                                            RT_NULL,
                                            &thread2_stack[0],
                                            sizeof(thread2_stack),
                                            THREAD_PRIORITY - 1, THREAD_TIMESLICE);
            rt_thread_startup(&thread2);


            return 0;
    }
    /* 导出到 msh 命令列表中 */
    MSH_CMD_EXPORT(semaphore_sample, semaphore sample);






    文章出处:恩智浦MCU加油站

    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    难过
    2023-9-6 15:15
  • 签到天数: 211 天

    [LV.7]常住居民III

    34

    主题

    805

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2038
    最后登录
    2024-3-21
    发表于 2019-12-5 10:07:41 | 显示全部楼层
    这是wifi使用的么,好高级的样子
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-28 00:06 , Processed in 0.121399 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表