君正X2100 RTOS 固件升级

        使用cloner工具烧写固件需要在上电之前让boot_sel[2:0]处于boot from USB模式,但是电路板装在机壳内部后不方便改变boot_sel[2:0]的状态,如果要升级固件,需要通过机壳留出的USB口、网口、或者无线网络进行固件更新。

一、升级方案

1、固件分析

        X2100的固件由两部分组成,bootloader和rtos app,spl bin文件就是bootloader,启动时由处理器内部固化的代码将bootloader拷贝到DDR,然后执行bootloader,bootloader再将rtos app拷贝到DDR,再执行rtos app。rtos app拷贝到DDR的地址由config文件指定,可通过配置界面->通用选项查看或修改。

2、启动流程

 再增加一个二级bootloader,启动流程改为spl--->2ndboot--->RTOS App。

二、开发二级bootloader

1、修改配置文件

创建一个应用,配置文件只保留一些基本功能。

设置固件使用的内存大小为3MB,剩余的留给RTOS App,所以这个够用就行。

开启USB CDC功能 :

2、程序

参考sdk /freertos/example/usb/device/gadget_cdc_serial_boot_app.c文件。代码运行逻辑:

1、创建cdc_serial接收线程;

2、接收到上位机发送的boot-app消息后执行boot-app()函数;

3、boot-app()先查找指定的镜像分区,需要和cloner烧录工具中指定的名字一样;

        #define PARTITON_NAME "app"

4、查找到分区后检查镜像的头部内容,如果头部内容的tag是0x534f5452(“RTOS”)再判断头部内容中指定的内存加载地址是否和当前运行的程序冲突,没有冲突就继续执行,有冲突就立即退出。

 5、将镜像的内容从拷贝到镜像头部内容指定的地址,然后运行。

3、文件内容
#include <stdio.h>
#include <cpu/irqflags.h>
#include <driver/irq.h>
#include <cpu/cpu.h>
#include <common.h>
#include <usb/gadget_serial.h>
#include <os.h>
#include "filesystem/include/mtd_driver_nor.h"#define PARTITON_NAME "app"struct rtos_header {unsigned int code[2];unsigned int tag;unsigned int version;unsigned long img_start;unsigned long img_end;unsigned long heap_start;unsigned long heap_end;unsigned long mapped_rtosdata_size;
};static const struct gadget_id serial_id = {.vendor_id = 0x0525,.product_id = 0xa4a7
};static const struct usb_cdc_serial_param serial_parameters ={.dwDTERate = 115200,.bCharFormat = USB_CDC_1_STOP_BITS,.bParityType = USB_CDC_NO_PARITY,.bDataBits = 8
};static void serial_param_callback(struct usb_cdc_serial_param *p)
{printf("usb serial: dwDTERate %d, bCharFormat %d, bParityType %d, bDataBits %d\n",p->dwDTERate, p->bCharFormat, p->bParityType, p->bDataBits);
}static void serial_connect_callback(int connect)
{printf("serial_connect_callback %d\n", connect);
}static inline int rtos_check_header(struct rtos_header *rtos)
{if (rtos->tag != 0x534f5452) {printf("rtos bad tag: %x\n", rtos->tag);return -1;}if (rtos->img_start >= rtos->img_end) {printf("rtos bad off: %lx %lx\n", rtos->img_start, rtos->img_end);return -1;}return 0;
}static inline int rtos_check_intersection(unsigned int start0, unsigned int end0, unsigned int start1, unsigned int end1)
{if (start1 < start0 && end1 < start0)return 0;if (start1 >= end0 && end1 >= end0)return 0;return 1;
}static inline void rtos_start(struct rtos_header *rtos, void *arg)
{void (*func)(void *arg) = (void *)rtos->img_start;flush_cache_all();func(arg);
}static void release_all_resources(void)
{usb_core_exit();local_irq_disable();arch_deinit_cpu();// lcd// disable_irq(IRQ_LCD);// release_irq(IRQ_LCD);// intcdisable_irq(IRQ_V_IP2);release_irq(IRQ_V_IP2);// ostdisable_irq(IRQ_V_IP4);release_irq(IRQ_V_IP4);local_irq_enable();
}int read_rtos_start_addr_by_name(struct rtos_header *rtos, int *offset, const char *find_node_name)
{struct mtd_nor_partition *mtd_part;struct mtd_nor_partition *parts = sfc_nor_flash_partition_information();if (parts == NULL) {return -EIO;}for (mtd_part = parts; mtd_part->name != NULL; mtd_part++) {if ( !strcmp(find_node_name, mtd_part->name) ) {*offset = mtd_part->offset;sfc_nor_flash_read( mtd_part->offset, sizeof(struct rtos_header), (void *)rtos);break;}}return 0;
}static void boot_app(void)
{int ret = 0;int offset = 0;struct rtos_header *rtos = malloc(sizeof(struct rtos_header));assert(rtos != NULL);memset(rtos, 0, sizeof(struct rtos_header));// 根据烧录工具中设置的分区名字获取镜像信息ret = read_rtos_start_addr_by_name(rtos, &offset, PARTITON_NAME);if (ret != 0) {printf("get partition_information fail!\n");goto error;}if (rtos_check_header(rtos)) {goto error;}// 检查加载是否会覆盖到旧系统地址上if (rtos_check_intersection(CONFIG_OS_MEM_ADDR, (CONFIG_OS_MEM_ADDR + CONFIG_OS_MEM_SIZE), rtos->img_start, rtos->img_end)) {printf("address overlap\n");goto error;}sfc_nor_flash_read(offset, rtos->img_end -rtos->img_start, (void *)rtos->img_start);release_all_resources();rtos_start(rtos, NULL);error:free(rtos);return ;
}static unsigned char usb_test_buf[1024];static void usb_gadget_serial_thread(void *data)
{int len, i;while (1) {msleep(1000);len = gadget_serial_read(usb_test_buf, sizeof(usb_test_buf), 0, 0);if (len > 0) {for (i = 0; i < len; i++){printf("usb read %c\n", usb_test_buf[i]);}if ( !strncmp(usb_test_buf, "boot-app", strlen("boot-app"))) {boot_app();}}}
}int application_2nd_boot_app(void)
{gadget_serial_init(&serial_id, &serial_parameters, serial_connect_callback, serial_param_callback);thread_create("usb gadget serial thread", 8192, usb_gadget_serial_thread, NULL);return 0;
}

三、开发应用

1、修改配置文件

        修改配置,不选spl文件,固件加载的地址需要≥二级bootloader的固件加载的地址+固件使用的内存大小,固件使用的内存大小为总的DDR大小 - 二级bootloader固件使用的内存大小 - 其余部分。如X2100的DDR大小是64MB,二级bootloader固件使用的内存大小是3MB,其余部分是1MB,那么应用的固件使用的内存大小是62914560(60MB)。

2、编译生成固件

        修改配置文件之后先make 配置文件,然后执行make,在freertos目录下会生成一个zero.bin,可将其改为其它名字。

四、烧录和测试

 1、SFC添加分区

启动cloner->配置->SFC->分区信息->添加一个app分区:

2、添加app烧录

3、 测试

        烧录之后,设备运行的是二级bootloader的程序,用上位机给设备的CDC串口发送"boot-app"消息,二级bootloader会将app.bin拷贝到指定的内部地址,然后运行。

五、更新app

        可在二级bootloader程序程序中加入Y-mode文件接收程序,上位机发送新的app.bin文件给设备,覆盖当前app.bin所在flash的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3361.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop——Yarn基础架构

Hadoop——Yarn基础架构 Hadoop YARN&#xff08;Yet Another Resource Negotiator&#xff09;是Apache Hadoop生态系统中的一个子项目&#xff0c;它是用于集群资源管理的框架&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统平台&…

Postman 工具发送请求的技巧与实践

在开发和测试 API 时&#xff0c;发送 JSON 格式的请求是一个常见需求。 在 Postman 中构建和发送 JSON 请求 创建一个新的请求 首先&#xff0c;在 Postman 启动界面上找到并点击 “New” 按钮&#xff0c;选择 “HTTP Request” 来开始新建一个请求。这一步骤允许你定义请…

指针学习总结

当指针本身定义的类型不同十&#xff0c;指向的一次性取值长度也不同 数组元素的指针 数组存放字符串 数组存放字符串时存放在栈区&#xff0c;sizeof(str1) 128字节 字符指针指向字符串 str2此时存放的是h的地址&#xff0c;因此sizeof(str2) 4字节或者8字节 并且文字常量…

递归算法/斐波那契数列

目录 递归 直接递归 间接递归 思想沿用 斐波那契数列 图片来源网络&#xff0c;侵权联系可删 递归 递归&#xff08;Recursion&#xff09;是一种编程技术&#xff0c;其中函数或方法直接或间接地调用自身。递归通常用于解决可以分解为更小、更简单的子问题的问题。递归的…

一文速览Llama 3及其微调:如何通过paper-review数据集微调Llama3 8B

前言 4.19日凌晨正准备睡觉时&#xff0c;突然审稿项目组的文弱同学说&#xff1a;Meta发布Llama 3系列大语言模型了 一查&#xff0c;还真是 本文以大模型开发者的视角&#xff0c;基于Meta官方博客的介绍&#xff1a;Introducing Meta Llama 3: The most capable openly a…

linux 系统文件目录颜色及特殊权限对应的颜色

什么决定文件目录的颜色和背景&#xff1f; 颜色 说明 栗子 权限白色表示普通文件 蓝色表示目录 绿色表示可执行文件 浅蓝色链接文件 黄色表示设备文件 红色 表示压缩文件 红色闪烁表示链接的文件有问题 灰色 表示其它文件 可以用字符表示文件的类型&am…

Netty快速入门

网络通信模型 在了解Netty之前&#xff0c;我们可以简单的先了解一下我们的网络通信方式&#xff0c;正所谓知其然&#xff0c;知其所以然。只有了解了网络通信模型&#xff0c;我们才能更好的去理解Netty的一些核心的原理。 如下图是一个简单的请求发送的时候的一个大概的HTT…

【Linux】GDB调试器学起来!指令全解,建议收藏

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

面试十五 容器

一、vector容器 template<typename T> class Allocator{ public:T* allocator(size_t size){// 负责内存开辟return (T*)malloc(sizeof(T) * size);}void deallocate(void * p){free(p);}void construct(T*p,const T&val){// 定位newnew (p) T(val);}void destroy(…

访问控制列表配置实验

ACL&#xff0c;全称 Access Control List&#xff08;访问控制列表&#xff09;&#xff0c;是一种实现访问控制的机制&#xff0c;用于规定哪些主体&#xff08;如用户、设备、IP地址、进程等&#xff09;可以对哪些资源&#xff08;如网络服务、文件、系统对象等&#xff09…

2024深圳杯C题的8页思路分析+所有代码可执行+参考文献+持续更新参考论文(已经更新了代码与图像)

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

docker入门学习

一、docker概念 Docker 引擎是使用的是Linux内核特性的容器引擎。 二、docker的安装 1.docker&#xff0c;下载地址&#xff1a; 桌面版&#xff1a;Docker Desktop: The #1 Containerization Tool for Developers | Docker 服务器版&#xff1a;Install Docker Engine | D…

# 从浅入深 学习 SpringCloud 微服务架构(六)Feign(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;六&#xff09;Feign&#xff08;3&#xff09; 一、组件的使用方式总结 1、注册中心 1&#xff09; Eureka 搭建注册中心 引入依赖 spring-cloud-starter-netflix-eureka-server。 配置 EurekaServer。 通过 EnableEure…

前端路由的实现原理

当谈到前端路由时&#xff0c;指的是在前端应用中管理页面导航和URL的机制。前端路由使得单页应用&#xff08;Single-Page Application&#xff0c;SPA&#xff09;能够在用户与应用交互时动态地加载不同的视图&#xff0c;而无需每次都重新加载整个页面。 在前端开发中&…

如何在阿里云快速配置自动定时重启ECS云服务器?

背景 无论是电子商务、在线教育、游戏&#xff0c;还是流媒体等业务&#xff0c;服务器的稳定运行都是至关重要的。然而&#xff0c;在实际运行中&#xff0c;我们可能会遇到这样一些场景&#xff1a; 系统更新&#xff1a;一些操作系统或者软件的更新可能需要重启服务器才能…

bit、进制、位、时钟(窗口)、OSI七层网络模型、协议、各种码

1.bit与进制 &#xff08;个人理解&#xff0c;具体电路是非常复杂的&#xff09; 物理层数据流&#xff0c;bit表示物理层数据传输单位&#xff0c; 一个电路当中&#xff0c;通过通断来表示数字1和0 两个电路要通讯&#xff0c;至少要两根线&#xff0c;一根作为电势参照…

Java中使用Graphics2D绘制字符串文本自动换行 算法

效果&#xff1a; 代码&#xff1a; /*** return void* Author xia* Description //TODO 写字换行算法* Date 18:08 2021/4/1* Param []**/private static void drawWordAndLineFeed(Graphics2D g2d, Font font, String words, int wordsX, int wordsY, int wordsWidth) {FontD…

东北大学工程训练CNC加工中心(坤图)

东北大学加工中心&#xff08;CNC&#xff09;采用的系统为FANUC系统。 要求学生自主设计图样&#xff0c;编写GCODE文件&#xff0c;操作电脑使机床按设计路径铣出图案。 本人设计的图样为坤坤图 图为用CAD设计绘制的图样。 计算坐标&#xff0c;设计铣刀轨迹&#xff0c;得…

Linux--基础IO(上)

目录 1. 文件的边角知识 1.1 文件是什么&#xff1f; 1.2 文件是怎么打开的&#xff1f; 1.3 进程与文件 进程与文件的关系 2. 重温c语言文件接口 2.1 打开文件的方式 2.2 读写文件接口的重温 2.2.1 写文件 2.2.2 读文件 3. 系统文件I/O 3.1 系统接口 3.2 系…

【深度学习-第5篇】使用Python快速实现CNN分类(模式识别)任务,含一维、二维、三维数据演示案例(使用pytorch框架)

在之前的文章中介绍了CNN的图解入门&#xff0c;CNN的MATLAB分类实现&#xff0c;CNN的MATLAB回归实现。 卷积神经网络(Convolutional Neural Networ&#xff0c;简称CNN)是一种广泛应用于图像识别领域的深度学习算法。它通过模拟人类视觉系统的层次结构&#xff0c;可以自动提…