0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在MCU上进行实际的部署

恩智浦MCU加油站 来源:恩智浦MCU加油站 作者:恩智浦MCU加油站 2022-08-11 09:02 次阅读

本篇将是系列文章的最后一篇,在MCU上进行实际的部署。 小编就不再给大家复习历史了,直接开始正题。如果想温习前两部分内容,请点击此处和此处。

首先给大家介绍一下我们将要使用的离线Flash烧写工具,名为JFlashLite,他有一个兄弟叫JFLash,既然是Lite就是轻量版本的JFlash工具。

当然,需要大家自行下载Segger Jlink工具包。是的,我们需要一条JLink。随后找到JFlashLite工具,他长这样(请忽略这里的1176,我们还没有配置):

ca0e5400-190c-11ed-ba43-dac502259ad0.png 比起下图他的哥哥JFlash,是不是很清爽的界面: ca385c6e-190c-11ed-ba43-dac502259ad0.png

当然,我们今天的主角是JFlashLite,稍后会介绍如何进行配置并下载

程序编写

工具介绍完了,下面正式开始编写配套程序,所使用的平台是i.MX RT1060, 开发板是IMXRT1060EVKB:

划分FLASH以及sdram区域,sdram区域负责加载flash中内容,加速内存访问:我们的开发板上有一个8MB的Flash,内存映射地址为0x60000000,首先保留1MB的头部区域以存储代码,其作用后续会提到。那么我们就剩下7MB大小的空间,由于数据一般较大,划分4MB作为数据存储区,剩下的3MB存储模型。同样的,在sdram区域,内存映射地址为0x80000000也同样开辟这样大的两块内存区,不过,为了防止数据溢出,我们仅针对于sdram区域,在数据区和模型区中间插入256B的数据保护区,并填充0xdeadbeef,最终的内存布局如下:

Flash上内存分配

ca5d443e-190c-11ed-ba43-dac502259ad0.png

Sdram内存分配

ca6d6f08-190c-11ed-ba43-dac502259ad0.png

利用JflashLite工具进行烧写:

打开JFlashLite工具点击…选择器件为1062xxxxA:

ca83319e-190c-11ed-ba43-dac502259ad0.png

选择对应的数据文件以及模型进行烧写,烧写地址要依据上述定义的分配,即模型数据烧写到0x60100000,图像数据烧写到0x60400000:

caa07470-190c-11ed-ba43-dac502259ad0.png

cac7d83a-190c-11ed-ba43-dac502259ad0.png

选择好之后,点击Program Device即可进行烧写;针对于模型数据,yao注意将以.tflite结尾的模型文件,重命名为.bin文件。

Scf文件编写,主要考虑到,运行时,将flash中的数据,拷贝到sdram中,以提高运行速度,这里声明两个区域负责存储ER_tflite_model以及ER_test_data

#define m_text_start                   0x80000400
#define FLASH_LOAD 7 * 1024 * 1024
LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_start {   ; load region size_region
  VECTOR_ROM m_interrupts_start FIXED m_interrupts_size { ; load address = execution address
    * (.isr_vector,+FIRST)
  }
  ER_m_text m_text_start FIXED m_text_size - FLASH_LOADER_SIZE { ; load address = execution address
    * (InRoot$$Sections)
    .ANY (+RO)
  }
 
#if (defined(FLASH_LOAD))
  ER_ test_data +0 EMPTY 4 * 1024 * 1024 {}
  ER_PLACEHOLDER1 +0 EMPTY FILL 0xdeadbeef 256{} 
  ER_tflite_model +0 EMPTY 3 * 1024 * 1024 {}  
  ER_PLACEHOLDER2+0 EMPTY FILL 0xdeadbeef 256{}
  ER_EMPTY m_text_start + m_text_size EMPTY 0{}
#endif

主代码编写,针对于边界溢出检测代码,简单起见,只检测首地址处值,不同则表示溢出,死循环等待

typedef struct {
uint32_t n, h, w, c;
uint8_t data[0];
}data_t;
// use a split area, total 7MB:
// tflite model 3MB
// img_data 4MB
#define FLASH_BASE (0x60100000)
#define MB(x)  (x * 1024 * 1024)

#define lr_model_data_len (MB(3))
#define lr_model_data  FLASH_BASE
#define lr_model_data_end (lr_model_data + lr_model_data_len)

#define lr_img_data_len  (MB(4))
#define lr_img_data  (lr_model_data_end)  // 0x60200000
#define lr_img_data_end (lr_img_data + lr_img_data_len)

// declare the sdram memory
extern uint8_t Image$$ER_tflite_model$$ZI$$Base[];
#define model_data Image$$ER_tflite_model$$ZI$$Base

extern uint8_t Image$$ER_test_data$$ZI$$Base[];
#define img_data Image$$ER_test_data$$ZI$$Base

extern uint8_t Image$$ER_PLACEHOLDER1$$ZI$$Base[];
#define PLACEHOLDER1 Image$$ER_PLACEHOLDER1$$ZI$$Base

extern uint8_t Image$$ER_PLACEHOLDER2$$ZI$$Base[];
#define PLACEHOLDER2 Image$$ER_PLACEHOLDER2$$ZI$$Base

#define DO_MEMCPY(name) memcpy((void*)name, (void*)lr_##name, lr_##name##_len)
#define PRE_INIT() 
    do{ 
DO_MEMCPY(model_data);
DO_MEMCPY(img_data); 
            while(0xdeadbeef != *(uint32_t*) PLACEHOLDER1) ;   
                         while(0xdeadbeef != *(uint32_t*) PLACEHOLDER2) ;          
    }while(0);

定义好了一些宏之后,就是模型的初始化函数:

void tflite_engine_init(){
#ifdef FLASH_LOAD
PRE_INIT()
#endif
SysTick_Config(CLOCK_GetCoreSysClkFreq() / 1000);
MODEL_AllocateTensor((void*)tensorArena, sizeof(tensorArena));
if (MODEL_Init(model_data) != kStatus_Success)
    {
        PRINTF("Failed initializing model");
        for (;;) {}
    }
}

测试数据如何获取呢,利用我们刚才定义的data_t结构体:

data_t *image = (data_t*)img_data;
image_data_ptr = image->data;

这样,我们就拿到了存储在flash并且已经被搬运到了sdram上的数据了,接下来就是编译运行了。

实际运行与测试

测试时候,要注意首先确保我们的开发板已经是XIP启动,即从Nor Flash启动,并且保证在flash的头部,烧写过一个完整的可执行镜像,比如hello_world程序,其中会包含Flash的一些配置信息,这一步小编就不再举例,还请大家自行准备。

这样,我们的BootRom会据此帮我们配置好Flash,程序中就不用手动调用Flash的初始化代码了。

还要注意,代码要全部运行在SDRAM或是其他介质上,因为我们已经将flash据为己有了。

下面是内存镜像的样子,首先是model:

caed9214-190c-11ed-ba43-dac502259ad0.png

再者是测试数据,前四个uint32类型的数据刚好是小编这里定义的数据长度100张128*128*3的rgb彩色图:

cb15207c-190c-11ed-ba43-dac502259ad0.png

连上板子和PC,并打开串口控制台即可查看输出结果,小编所选用的模型是一个水果识别的模型,下面是最后一组数据的输出结果,证明我们的程序运行成功!

cb448380-190c-11ed-ba43-dac502259ad0.png

展望

当然,小编给大家分享的这个方法,不仅可以应用在神经网络AI推理上,可以当作一个低配版的flashloader,以供大家灵活地更新静态数据资源。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    16840

    浏览量

    349735
  • FlaSh
    +关注

    关注

    10

    文章

    1613

    浏览量

    147632
  • 工具包
    +关注

    关注

    0

    文章

    45

    浏览量

    9514

原文标题:一种基于MCU的神经网络模型在线更新方案之MCU实战篇

文章出处:【微信号:NXP_SMART_HARDWARE,微信公众号:恩智浦MCU加油站】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    何在资源有限的MCU上进行图形应用设计

    第二种是以NXP官方推出的GUI Guider为代表的动态加载策略,即只加载在系统启动后显示的屏幕,后面如果需要显示哪一个屏幕再动态加载。
    发表于 10-20 09:56 2825次阅读

    何在TINA上进行电荷放大器的仿真?

    想请问一下,电荷放大器选用什么样的运放比较好,仪器放大器可以吗? 如何在TINA上进行电荷放大器的仿真?
    发表于 08-19 06:18

    何在原电路上进行添加保护电路和修改 ,请高手指导!

    刚毕业的小白 领导让设计拾音器 有一篇TI家最简单的电路资料,经过元器件和选型后,确定了麦克风用PUI家POM-3535L,放大器用TI的OPA172,脉冲调制用TI的PCM1800E,但只能实现简单声音信号,如何在原电路上进行添加保护电路和修改 ,请高手指导!
    发表于 11-07 16:53

    何在最大分辨率的LCD上进行DouthGaSUS分布?

    何在最大分辨率的LCD上进行DouthGaSUS分布?请你帮帮我好吗?
    发表于 08-16 09:07

    何在STM32F103上进行CAN通信的管脚重映射配置和使用

    CAN通信管脚重映射1. 摘要本篇笔记主要介绍,如何在STM32F103上进行CAN通信的管脚重映射配置和使用2. 准备工作1), IAR 8.3.12), 运行...
    发表于 08-19 06:20

    何在stm32f103上进行汇编语言测试呢

    何在stm32f103上进行汇编语言测试呢?有哪些步骤?
    发表于 10-08 08:45

    何在MCU上进行内存管理与分配

    从事嵌入式产品开发已有十余年了,从最开始的8051一直用到现在流行的Cortex M系列的内核的单片机。从最开始用VC6.0开发PC端的软件到现在使用Mircrosoft WPF框架进行PC端的软件开发。发现现在的新人对MCU的内存管理与分配上真是一无所知。我就谈谈如
    发表于 11-04 06:06

    何在MDK5上进行STM32设计跑马灯程序并进行编译及仿真?

    何在MDK5上进行STM32设计跑马灯程序并进行编译及仿真?
    发表于 11-10 07:57

    何在esp8266 Node MCU的硬件上部署LVGL

    前言本文,介绍如何在esp8266 Node MCU的硬件上部署LVGL项目。使用的屏幕使用型号是ST7735 TFT 128x128屏幕。(一)arduinoIDE esp8266环境配置自行
    发表于 12-08 07:15

    何在MCU片内进行Flash读写呢

    何在MCU片内进行Flash读写呢?其过程是怎样的?
    发表于 12-13 06:51

    何在Ubuntu系统上进行中文支持

    1、Ubuntu系统上进行中文支持Firefly 的Ubuntu系统默认是英文版,现在刚刚发布了最新的双系统固件Ubuntu上有了很多更新。这里就顺便说明下如何在Ubuntu系统上进行中文支持:这是
    发表于 06-13 17:21

    在FPGA上进行图像处理及其示例

    借助FPGA技术和NI视觉开发模块,您可以对从相机采集的图像进行高速现场可编程门阵列(FPGA)处理。 FPGA处理尤其适用于要求图像采集和处理之间具有低延迟的应用。 本文概述了如何在FPGA上进行图像处理。
    发表于 11-17 06:00 1.9w次阅读

    使用Devtron在Kubernetes多集群上进行开发

    在本文中,您将学习如何在多集群环境中使用 Devtron 在 K8S 上进行应用开发。
    的头像 发表于 11-17 09:50 799次阅读

    2分钟快速教你如何在华为模拟器ensp上进行抓包?

    2分钟快速教你如何在华为模拟器ensp上进行抓包?
    的头像 发表于 12-05 11:25 4322次阅读

    何在AT32 MCU上使用FPU功能

    何在AT32 MCU上使用FPU功能
    的头像 发表于 11-01 17:18 3963次阅读
    如<b class='flag-5'>何在</b>AT32 <b class='flag-5'>MCU</b>上使用FPU功能