当前位置: 首页 > news >正文

google 网站质量问题浏览器下载安装2023版本

google 网站质量问题,浏览器下载安装2023版本,天地做网站,360 街景地图这个系列参考了《嵌入式实时操作系统RT-Thread设计与实现》,会详细介绍RT-Thread的启动流程,即是如何从零开始在开发板上运行起一个RTOS内核的。本文将会以 ch32v307VCT6 开发板为例展开进行详细介绍。主要包括:startup.S、初始化与系统相关的…

        这个系列参考了《嵌入式实时操作系统RT-Thread设计与实现》,会详细介绍RT-Thread的启动流程,即是如何从零开始在开发板上运行起一个RTOS内核的。本文将会以 ch32v307VCT6 开发板为例展开进行详细介绍。主要包括:startup.S、初始化与系统相关的硬件、初始化系统内核对象(例如定时器、调度器、信号)、创建main线程、初始化线程并启动调度器 这五大部分。

        在这一小节中,本文将讲述通过wsl烧录RT-Thread的基本流程。并在最后讲解startup_ch32v30x.S文件的执行过程。

一、系统运行环境

        本文在Linux系统上通过命令行的方式实现RT-Thread的下载与调试。这有几个准备步骤:

  • RT-Thread的源码获取, 在linux命令行中输入如下命令:
    git clone https://gitee.com/rtthread/rt-thread.git
  • 交叉编译工具链的下载:MRS_Toolchain_Linux_x64_V1.92.1.tar.xz 下载地址。下载好后在linux环境中解压。记录好下载路径
  • Scons工具下载: 在Linux命令行中输入以下命令:
    sudo apt install scons

        准备完毕后,切换目录到:./RT_thread/rt-thread/bsp/wch/risc-v/ch32v307v-r1 下运行(下文称其为根目录):

    scons --exec-path=../../../../../Toolchain_linux/MRS_Toolchain_Linux_x64_V1.92.1/RISC-V_Embedded_GCC/bin

        其中--exec-path=后接下载的交叉编译工具链的路径。运行成功如下所示:

        至此在当前目录下会生成rtthread.bin 和 rtthread.elf两个文件。前期的准备工作就到此结束。

二、烧录至开发板

        本文使用wsl,安装教程:WSL2 最新最全帮助小白一步步详细安装教程。

        由于wsl本身不支持usb连接,因此需要把插入电脑的usb(Windows下)接入到wsl(Linux下)中,所以还需要安装usbipd-win开源项目:usbipd-win安装。想要便捷操作的可以额外下载图形化界面wsl usb gui:wsl usb gui 下载。

        下载完成,并且usb成功接入到wsl后,为了方便操作一般都会有一个Makefile执行相关命令,其中的相对路径均从之前下载的交叉编译工具链给出:

CROSS_COMPILE := ../../../../../Toolchain_linux/MRS_Toolchain_Linux_x64_V1.92.1/RISC-V_Embedded_GCC/bin/riscv-none-embed-
OPENOCD_DIR = ../../../../../Toolchain_linux/MRS_Toolchain_Linux_x64_V1.92.1/OpenOCD/bin
OPENOCD = ${OPENOCD_DIR}/openocd
CFG = ${OPENOCD_DIR}/wch-riscv.cfg
GDB := ${CROSS_COMPILE}gdb
OBJDUMP  := ${CROSS_COMPILE}objdump
.DEFAULT_GOAL := allall:scons --exec-path=../../../../../Toolchain_linux/MRS_Toolchain_Linux_x64_V1.92.1/RISC-V_Embedded_GCC/bin.PHONY : flash
flash: @echo "------------------------"@echo "Flashing os.bin to board"@echo "------------------------"@${OPENOCD} -f ${CFG}  -c init -c halt  -c "program rtthread.bin"  -c exit.PHONY : run_openocd
run_openocd: @echo "-----------------------------------------------"@echo "Please manually kill the openocd after gbd quit"@echo "-----------------------------------------------"@${OPENOCD} -f ${CFG} &.PHONY : run_gdb
run_gdb:@${GDB} rtthread.elf -q -ex "target remote : 3333".PHONY : code
code: @${OBJDUMP} -d rtthread.elf > rtthread.asm.PHONY : clean
clean:rm -rf *.o *.bin *.elf

        把以上Makefile文件放在根目录下,并执行sudo make flash,即可成功烧录:

        使用picocom串口工具观察现象,picocom工具直接命令行输入sudo apt install picocom下载。在这里波特率为115200,默认8个数据位,1个停止位,不启用校验位。 /dev/ttyACM0为Linux系统所识别的新插入的开发板USB设备文件。按下ctrl+A   ctrl+X退出。

        当出现如下图所示的 RT 字样即说明成功启动RT-Thread。

三、startup_ch32v30x.S

        现在本文将从汇编文件开始,讲述RT-Thread是如何一步一步启动的。startup_ch32v30x.S位置在:RT_thread/rt-thread/bsp/wch/risc-v/Libraries/ch32v30x_libraries/bmsis/source

        汇编文件中的入口地址为 _start (由链接脚本ENTRY( _start )指定)。汇编文件中第13行至332行均在设置中断向量入口地址。   

        第345行在设置堆栈指针:

        第348行至357行在将.data段中的数据从flash搬移至ram:

        第360行至366行在清零 .bss 段中的数据:

        第368行至373行在写控制状态寄存器(具体作用不知):

        第377行至378行在写mstatus寄存器,mstatus寄存器结构如下图,其中比较重要的位有:

MIE:全局trap(中断和异常)开关。   

MPIE:trap前系统MIE位的状态,也可以理解为:执行mret时,MIE会被赋值位MPIE。 

MPP:trap前系统运行的模式。也可以理解为:mret时系统会运行于哪种模式。 为11则表示系统会运行在机器模式。

FS:11表示启动浮点运算

        因此这里在把MPP写为11后,执行mret就打开了全局trap(中断和异常)的开关 。

        第380行至382行在设置中断向量入口基地址,其中_vector_base在此汇编文件第29行指定。

        第384行至387行在执行开发板时钟初始化(SystemInit),并进入RT-Thread的初始化函数:

        在这里,mepc寄存器中存入了entry函数地址,在mret时,系统会跳转到mepc寄存器存放的地址继续执行,从而实现了entry函数的跳转。

SystemInit函数位置:

RT_thread/rt-thread/bsp/wch/risc-v/Libraries/ch32v30x_libraries/bmsis/source/system_ch32v30x.c:85

        首先执行SystemInit,个人认为由于系统复位,不管是哪种复位形式,寄存器都会被设置为复位值,所以SystemInit中,除了SetSysClock()函数的跳转,其他操作意义不明(我太菜了)。本文使用的ch32v307VCT6属于CH32V30x_D8C类别。

        除非是软件直接跳转到handel_reset执行复位逻辑。

void SystemInit (void)
{RCC->CTLR |= (uint32_t)0x00000001; #ifdef CH32V30x_D8CRCC->CFGR0 &= (uint32_t)0xF8FF0000; 
#elseRCC->CFGR0 &= (uint32_t)0xF0FF0000; 
#endif RCC->CTLR &= (uint32_t)0xFEF6FFFF;RCC->CTLR &= (uint32_t)0xFFFBFFFF;RCC->CFGR0 &= (uint32_t)0xFF80FFFF;#ifdef CH32V30x_D8CRCC->CTLR &= (uint32_t)0xEBFFFFFF;RCC->INTR = 0x00FF0000;RCC->CFGR2 = 0x00000000;
#elseRCC->INTR = 0x009F0000;   
#endif   SetSysClock();
}

在SetSysClock中将系统时钟设置为定义好的144MHz:

static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSESetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHzSetSysClockTo24();
#elif defined SYSCLK_FREQ_48MHzSetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHzSetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHzSetSysClockTo72();
#elif defined SYSCLK_FREQ_96MHzSetSysClockTo96();
#elif defined SYSCLK_FREQ_120MHzSetSysClockTo120();
#elif defined SYSCLK_FREQ_144MHz  //仅144MHz有宏定义SetSysClockTo144();#endif/* If none of the define above is enabled, the HSI is used as System clock* source (default after reset) */ 
}

        在SetSysClockTo144()函数中。主要工作在 启用HSE时钟,配置PLL倍频、设置系统时钟、HCLK、PB1\PB2外设时钟

        逻辑是先启用HSE外部8MHz高速时钟,并PLL 18倍频至 144MHz 作为SYSCLOCK系统时钟。 系统时钟不分频作为HCLK的输入。 HCLK不分频作为PB2CLK输入, HCLK 2分频作为PB1CLK输入。

static void SetSysClockTo144(void)
{__IO uint32_t StartUpCounter = 0, HSEStatus = 0;RCC->CTLR |= ((uint32_t)RCC_HSEON); //启用外部高速时钟/* 等待HSE时钟准备就绪 */do{HSEStatus = RCC->CTLR & RCC_HSERDY;StartUpCounter++;} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));/* 判断HSE是否准备就绪 */if ((RCC->CTLR & RCC_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}/* 如果HSE准备就绪则配置PLL倍频、SYSCLK、HCLK、PB1CLK、PB2CLK */if (HSEStatus == (uint32_t)0x01){/* HCLK = SYSCLK */RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; //设置HCLK为SYSCLK不分频输入/* PCLK2 = HCLK */RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; //设置PB2CLK为HCLK不分频输入/* PCLK1 = HCLK/2 */RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; //设置PB1CLK为HCLK2分频输入/*  PLL 配置: PLLCLK = HSE * 18 = 144 MHz */RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLMULL));#ifdef CH32V30x_D8RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
#elseRCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL18_EXTEN); //配置PLL时钟源为HSE,并设置18倍频。 实际上这里配置的PLL时钟源是prediv1,只不过prediv1系统默认输入是HSE不分频输入。
#endif/* 启用 PLL */RCC->CTLR |= RCC_PLLON;/* 等待 PLL 准备就绪 */while((RCC->CTLR & RCC_PLLRDY) == 0){}/* 设置 PLL倍频时钟 作为系统时钟 */RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;/* Wait till PLL is used as system clock source */while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08){}}else{/** If HSE fails to start-up, the application will have wrong clock* configuration. User can add here some code to deal with this error*/}
}

        至此系统从汇编文件启动,到跳转到RT-Thread的初始化入口entry函数的逻辑就讲解完毕。这一部分主要是开发板启动的常规操作(数据段搬运、bss段清零、中断向量设置),以及 系统时钟的配置。接下来将介绍entry函数中是如何对RT-Thread进行初始化的。

四、RT-Thread初始化

        单核初始化过程包括:中断关闭、板级初始化、定时器初始化、调度器初始化、信号初始化、初始化创建应用main线程、初始化创建定时器线程、空闲线程初始化、僵尸线程初始化、打开中断并进行线程调度。

int rtthread_startup(void)
{
#ifdef RT_USING_SMPrt_hw_spin_lock_init(&_cpus_lock);
#endifrt_hw_local_irq_disable(); //关中断/* board level initialization* NOTE: please initialize heap inside board initialization.*/rt_hw_board_init(); //板级初始化/* show RT-Thread version */rt_show_version();/* timer system initialization */rt_system_timer_init(); //定时器初始化/* scheduler system initialization */rt_system_scheduler_init(); //调度器初始化#ifdef RT_USING_SIGNALS/* signal system initialization */rt_system_signal_init();
#endif /* RT_USING_SIGNALS *//* create init_thread */rt_application_init(); //创建用户线程/* timer thread initialization */rt_system_timer_thread_init(); //定时器线程初始化/* idle thread initialization */ rt_thread_idle_init(); //空闲线程初始化/* defunct thread initialization */rt_thread_defunct_init(); //僵尸线程初始化#ifdef RT_USING_SMPrt_hw_spin_lock(&_cpus_lock);
#endif /* RT_USING_SMP *//* start scheduler */rt_system_scheduler_start(); //线程调度,开中断并执行main函数/* never reach here */return 0;
}

        其中rt_hw_boart_init板级初始化过程需要我们根据具体的开发板进行修改。需要在其中完成系统时钟配置、为系统提供心跳、串口初始化、将系统输入输出终端绑定到这个串口。

extern uint32_t SystemCoreClock;static uint32_t _SysTick_Config(rt_uint32_t ticks)
{NVIC_SetPriority(SysTicK_IRQn, 0xf0);NVIC_SetPriority(Software_IRQn, 0xf0);NVIC_EnableIRQ(SysTicK_IRQn);NVIC_EnableIRQ(Software_IRQn);SysTick->CTLR = 0;SysTick->SR = 0;SysTick->CNT = 0;SysTick->CMP = ticks - 1;SysTick->CTLR = 0xF;return 0;
}/*** This function will initial your board.*/
void rt_hw_board_init()
{/* System Tick Configuration */_SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);
#endif/* USART driver initialization is open by default */
#ifdef RT_USING_SERIALrt_hw_usart_init();
#endif
#ifdef RT_USING_CONSOLErt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
#ifdef RT_USING_PIN/* pin must initialized before i2c */rt_hw_pin_init();
#endif/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INITrt_components_board_init();
#endif}void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void SysTick_Handler(void)
{GET_INT_SP();/* enter interrupt */rt_interrupt_enter();SysTick->SR = 0;rt_tick_increase();/* leave interrupt */rt_interrupt_leave();FREE_INT_SP();}

http://www.zhongyajixie.com/news/49933.html

相关文章:

  • 知名网站建设怎么样足球世界排名一览表
  • 做网站二维码优化资源配置
  • 潍坊哪家做网站做的最好开鲁视频
  • 张家港网站制作线上免费推广平台都有哪些
  • 企业网站建设 信科网络优化网站推广教程排名
  • 西安网站建设地址厦门人才网597人才网
  • 网站程序设计上海做网站优化
  • 政府门户网站建设的重点网盘搜索引擎入口
  • 后端开发网站做一些什么百度网址ip
  • uni做网站首页seo网络推广到底是做什么的
  • 工业园区网站建设方案合肥网络推广营销
  • 凡客诚品网站推广关键词百度云
  • 龙陵县住房和城乡建设局网站微指数查询入口
  • 域名建设好了怎么在建设网站写手接单平台
  • 新手学做网站 pdf 网盘游戏推广论坛
  • 平台类网站做多久比较好的免费网站
  • wordpress直接上传视频seo排名查询工具
  • metinfo 建站sem是什么意思啊
  • 中企动力做网站服务怎么样新媒体营销策略有哪些
  • 郑州建设工程交易中心网站北京百度seo
  • 石家庄商城网站搭建多少钱抖音推广平台
  • 泰州专业做网站直通车关键词怎么选 选几个
  • 武汉电脑网站制作公司html网页制作软件有哪些
  • 学做莱网站北京seo优化厂家
  • 怎么做代刷网站教程中国科技新闻网
  • 怎么做网站设计程序西安优化排名推广
  • wordpress 数据 拆分seo优化的主要任务
  • 电子商务官方网站建设教育培训机构官网
  • 学网页设计报班上海网站营销seo方案
  • php网站开发过程互动营销公司