网站开发设计流程图,网页制作模板扩展名,笔记本做系统哪个网站好,深圳市出行最新政策大家好转发一篇杂烩君的文章#xff0c;杂烩君是我同一个高中的老乡#xff0c;他平时分享的嵌入式知识非常不错。——————大家好#xff0c;我是杂烩君。最近#xff0c;朋友送了块小板子#xff0c;板子上的MCU是个很有意思的东西——并行多线程处理器MC3172 。通俗… 大家好转发一篇杂烩君的文章杂烩君是我同一个高中的老乡他平时分享的嵌入式知识非常不错。——————大家好我是杂烩君。最近朋友送了块小板子板子上的MCU是个很有意思的东西——并行多线程处理器MC3172 。通俗地说这颗MCU的内部实现了类似RTOS多线程的功能。但是MC3172 编程与RTOS编程的最大区别就是MC3172多线程绝对并行运行没有切换抖动及开销。MC3172无线程优先级、优先级反转、死锁等概念。MC3172所有中断都可以安排专门线程处理没有中断嵌套和延迟。MC3172各线程同步并行运行互不阻塞互不干扰。MC3172线程响应的确定性相对于RTOS更为精确。MC3172简介 MC3172 是厦门感芯科技的一款32 位 RISC并行多线程实时处理器。基于RISC-V RV32IMC 指令集 100%单周期指令 最高200MHz主频 3.37coremark/MHz。可以代替实时操作系统 实现程序的模块化与复用性。相关资料可在感芯官网下载。链接http://www.gxchip.cn/MC3172 特性MC3172实践 MC3172的开发环境使用的是国产软件——MounRiver Studio。MounRiver Studio下载链接http://www.mounriver.com/download我们简单看一下MC3172的demo工程1、MC3172文件夹MC3172存放MC3172编程核心文件。线程配置工具可对各线程进行配置可以配置线程时钟源、频率、栈空间、存储器分配等信息。MC3172支持64路线程同步并行运行 其中分为4个线程组每个线程组16线程每个线程组里的线程编号如上图所示。其中不使用的线程可以设置为空闲线程空闲线程完全不运行不产生功耗。每个线程都有自己独立的栈空间 在数据空间允许范围内可随意分配但需要确保所有非空闲线程所占的数据空间不超过数据空间的大小。MC3172.h存放外设地址相关宏定义及其配置宏如类似于ST的stm32fxxx.h。thread_config.h为线程配置文件由线程配置工具生成MC3172.lds为链接脚本由线程配置工具生成thread_start.c为启动线程相关的源文件#ifndef THREAD_START_C
#define THREAD_START_C
#include ./MC3172.h
#include ./thread_config.hvoid thread1_initial(void)
{
#ifdef ROTHD_THREAD1_VALID
extern void thread1_main(void);rothd_set_sp_const(ROTHD_THREAD1_STACKCFG_VALUE|0x20000000);thread1_main();
#endif
}
void thread2_initial(void)
{
#ifdef ROTHD_THREAD2_VALID
extern void thread2_main(void);rothd_set_sp_const(ROTHD_THREAD2_STACKCFG_VALUE|0x20000000);thread2_main();
#endif
}// 省略部分代码......
void (*thread_initial_pointer[64]) (void){thread0_initial,thread1_initial,thread2_initial
// 省略部分代码......
}void thread_start(void)
{(*thread_initial_pointer[THREAD_ID])();
}程序运行的入口函数为thread_start 从链接脚本里可以知道thread_start里的THREAD_ID为线程ID值直接从0x50000000地址中读出#define THREAD_ID (*(volatile u8*)(0x50000000))猜测0x50000000地址里的ID值会不断变化通过某种机制跳转遍历执行thread_initial_pointer函数指针数组里的各个线程函数。threadx_initial里初始化线程栈并执行线程主体如void thread_end(void)
{while(1);
}void thread1_main(void)
{while(1){//user code section}thread_end();
}这是用户代码我们可以在各个线程主体函数里边编写我们的应用代码。2、Release文件夹Release文件夹里存放的是编译生成的固件程序通过 开发板程序下载工具 可进行下载3、USER_CODE文件夹USER_CODE文件夹存放用户代码MC3172 是一颗并行并行多线程实时处理器我们下面来看看其多线程并行执行的特性。我们编写两个线程线程进行相同的配置两个线程分别对两个IO进行翻转测试代码如void LED0_GPIOA_PIN0_TEST(void)
{// 启动GPIOA并设置特权组及时钟频率INTDEV_SET_CLK_RST(GPIOA_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV2));// 使能GPIOA PIN0引脚GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR, GPIO_PIN0, GPIO_SET_ENABLE);while(1){// GPIOA PIN0输出1GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR, GPIO_PIN0);// 延时for (u32 var 0; var 5000; var){NOP();}// GPIOA PIN0输出0GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR, GPIO_PIN0);// 延时for (u32 var 0; var 5000; var){NOP();}}
}void LED1_GPIOA_PIN1_TEST(void)
{// 启动GPIOA并设置特权组及时钟频率INTDEV_SET_CLK_RST(GPIOA_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV2));// 使能GPIOA PIN1引脚GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR, GPIO_PIN1, GPIO_SET_ENABLE);while(1){// GPIOA PIN1输出1GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR, GPIO_PIN1);// 延时for (u32 var 0; var 5000; var){NOP();}// GPIOA PIN1输出0GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR, GPIO_PIN1);// 延时for (u32 var 0; var 5000; var){NOP();}}
}void thread_end(void)
{while(1);
}void thread0_main(void)
{while(1){//user code section}thread_end();
}void thread1_main(void)
{while(1){//user code sectionLED0_GPIOA_PIN0_TEST();}thread_end();
}void thread2_main(void)
{while(1){//user code sectionLED1_GPIOA_PIN1_TEST();}thread_end();
}烧录程序使用逻辑分析仪抓取GPIOA_PIN0及GPIOA_PIN1引脚电平变化如可见这两个波形是完全同步的CPU同时在干两件事情实现了与RTOS多线程同样的效果。心得与总结 嵌入式开发是软件硬件结合两者互补。如果硬件功能很强大则软件可能可以设计得比较简单如果硬件功能有限则软件方面可能得考虑比较多的方面。比如一些软件算法需要多传感器数据输入进行融合则功能实现可能比较简单但实际可能为了降成本减少一些传感器这时候需要实现稳定可靠的功能则软件算法上得下更大的功夫。对于一些不太复杂的数字信号处理在通用的MCU上就可以处理但对于一些比较复杂的数字信号处理则可能使用一些带有DSP处理器的MCU。特别的对于芯片内部IC电路来说如果内部有相关模块可以实现某些功能的话则对应的软件编程会简单很多而且硬件实现的比软件实现的效率要高。硬件实现的多线程编程确实优于RTOS编程但实际开发中产品软硬件架构需要考虑多个方面比如芯片的稳定性以及软件生态等方面。并行多线程实时处理器是个好东西但目前并行多线程实时处理器还处于起步阶段还有很多东西需要完善需要我们多支持与传播只有生态起来了将来我们才有机会用得上。以上就是本次的分享如果觉得文章有帮助麻烦帮忙转发谢谢