Changes from v2.7.7 to v2.7.8:
[feat]:upgrade patch tool to v3.8 [opt]:opt code generate process display [opt]:opt login logic [opt]:opt ghs support [opt]:add MC03 ghs support由于一些原因,我需要手动配置寄存器来收发发送spi报文(本机做master):
一下是我写参照Spi_SyncTransmit写的发送并接收的函数:
逻辑分析仪上,可见SO是有数据的,见下图:
c3f3a558-7e7b-403d-80b6-a9edaf890740-image.png
用Spi_SyncTransmit接口(上面注释中的代码)是正常收发的, 用Spi_SendTxData收不到.
求助,Spi_SendTxData中该如何做才能收到MISO上传输的数据?
Hello,
As I using the example code for FLASH
3a4954db-5296-42f1-a23f-cb61d182b8f8-image.png
The geranated code only has the PFLASH API. for APIs for DFLASH was marked with a macro "FEATURE_EFM_PROGRAM_DATA_CMD_CODE"
7a878edd-dd3f-4e30-b1e5-6540c18e2236-image.png
to use these API for DFLASH, do I have to do any configuration in the YT Config Tool? or just simply enable the macro to turn on the APIs?
Thank you
在YTM32Bx系列MCU中,可通过EFM模块ADDR_PROT寄存器对内部Flash进行写保护,ADDR_PROT寄存器中的每个bit被设置为0时,其对应的Flash区域即被写保护。MCU上电后ADDR_PROT寄存器值仅允许从1变为0,而不允许从0变为1,即MCU允许过程中Flash一旦被写保护,则本次运行期间不能被取消写保护。
EFM模块中ADDR_PROT寄存器的初始值来自于MCU内部CUS_NVR Flash中指定位置(详见MCU参考手册),用户可根据自身需求通过写CUS_NVR Flash设置该寄存器的默认值,需注意,若该寄存器默认值被设置为0,则MCU上电后对齐的Flash即被写保护,后续将无法通过JTAG或软件内部的Flash driver对被写保护的Flash进行擦除或编程操作。
此时如果需要解锁被写保护的Flash,则只能通过重置ADDR_PROT寄存器初始值,即擦除重写CUS_NVR Flash中对应位置的值。若MCU内部所有Flash均被写保护,则该MCU无法在向Flash中下载任何程序,此时若需修改ADDR_PROT寄存器初始值,则需新建一个工程用于擦除CUS_NVR Flash,并将该工程所有代码放在RAM中运行.
下面以YTM32B1MD14为例介绍实现过程:
1.在YCT工具中新建工程,并配置YT-LINK模块,删除该模块中Flash中配置的所有sector信息,并在RAM中创建.text段以及.rodata段,用于存储代码及const类型数据。
85fb3330-3100-4864-9c0c-4c98873fe6bc-image.png
2.在main.c中通过如下代码实现CUS_NVR擦除。
uint32_t TestCnt=5; void Test_CusterNvrErase(void) { EFM->CUS_KEY = 0x4dff32; EFM->CMD = 0U; EFM->STS = EFM_STS_FAIL_MASK | EFM_STS_ACCERR_MASK | EFM_STS_UNRECOVERR_MASK | EFM_STS_RECOVERR_MASK | EFM_STS_DONE_MASK; EFM->NVR_ADDR = 0x10000400U; EFM->CMD_UNLOCK = 0xfd9573f5; EFM->CMD = 0x41U; while ((EFM->STS & EFM_STS_DONE_MASK) == 0U) { } if(((EFM->STS&EFM_STS_ACCERR_MASK) != 0)||((EFM->STS&EFM_STS_FAIL_MASK) != 0)) { while(1) {} } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ Board_Init(); /* USER CODE BEGIN 2 */ Test_CusterNvrErase(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { TestCnt++; if(TestCnt>1000) { TestCnt = 0; } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } static void Board_Init(void) { } 通过调试工具将代码下载至MCU运行,然后reset MCU即可完成Flash写保护解锁。4.注意示例代码中写入的CUS_KEY为MCU默认值,若MCU CUS_KEY被修改,则需根据实际情况写入KEY值。
Erase_CUSNVR.zip
本方案基于YT Config Tool开发,使用Vscode+Cmake+Ozone工具链开发编译调试;基于Demo板硬件搭建实施;使用同星科技TC1012P CAN/LIN工具及同星科技TSmaster软件。
ec4279d5-5d57-47ae-9be6-bab156b6ab19-image.png
由于LE04没有PTE6引脚,所以需要将CAN的使能脚短接到GND上
新建YTM32B1LE04的FLASH工程
8e247ddc-c8ce-4242-a560-ae1a1e35a7ec-image.png
找到Bootloader编译的烧程文件
28658dba-4133-418c-b374-97bae8eb0679-image.png
加载Bootloader文件
f10384f4-b329-4abd-a7e6-e4b41547e4f4-image.png
擦除芯片(或者快捷键F4)
66286636-2eef-4193-b610-1a260d065e22-image.png
63d914c6-b96c-40e9-b8cc-4c8d453175df-image.png
烧录程序(或者快捷键F6)
776cb472-05c7-423e-b1bc-bf49cd971626-image.png
e8064c9a-cfb0-436e-8ff9-ad36e9ce25e0-image.png
拔掉JLINK烧录器,重新上下电后,板子重新工作,LED按照100ms快速闪烁,程序工作在Bootloader里面。
3. 升级上位机配置将FlashDriver文件、Application文件、SeedAndKey.dll几个文件放到升级上位机目录下。
a87e2282-a011-4e91-8ed6-20e489c4b7a2-image.png
打开升级上位机工程(如上图中.TSProj_x86文件)配置收发ID
d677027f-b088-4da5-a18c-32faa9956d6d-image.png
配置TP时间参数,配置加密dll
4ae8991f-a8cb-4031-934b-d202932f462b-image.png
配置FlashDriver和Application和校验方式
eff13a22-d262-4bb0-b802-66b56bf40511-image.png
配置自动诊断流程
5aed28bc-fc62-4aad-9cec-27fde4977215-image.png
b38f4636-2600-46c9-8425-eb81dd6f113f-image.png
升级完成后,LED灯1000ms闪烁,运行在Application程序中。
从Bootloader升级成功运行到Application后,再次点击运行,从Application升级。
6fd55810-07a8-4d9a-b6ab-6defa44b3a45-image.png
升级完成后,LED灯1000ms闪烁,运行在Application程序中。
从Application升级中,是有升级请求标识的(KeepInBootVar变量)。
本方案设计上认为:
运行到Bootloader以后,如果通讯一半断开未发生升级服务(擦除芯片/请求下载/数据传输/下载退出等UDS服务),则即使有升级请求,可以超时退出重新跳转到Application运行;反之则必须StayInBoot等待重新升级。
升级一半,拔掉CAN线模拟通讯断开,升级失败
f39d35bf-938e-4322-8f88-cab1bcb5d7a5-image.png
通讯断开超时后,Bootloader重新进入Application运行,Demo板上LED灯1000ms闪烁。
4.3.2 已发生升级流程请求
执行到升级流程后,拔掉CAN线模拟通讯断开,升级失败
6ce78ee8-61f5-42e8-9934-a234b0cf04c8-image.png
通讯断开超时后,Boootloader不能进入Application,执行StayInBoot(重新复位或者上下电等均保持StayInBoot)。
重新执行升级
ff33eb5d-009b-4d44-a8d0-1e64bfc75b71-image.png
升级成功,Demo板上LED灯1000ms闪烁。
5. 附件代码
uds_can_fbl_le04_release_20250529.zip
参考SDK应用_Secure_Boot 模块配置及应用文档及RM手册中关于安全启动流程的描述,MCU的安全启动分为Normal Boot Mode和Fast wakeup Boot Mode两种,应用中常见的Secure boot启动方案如下:
bef340f4-2a46-41cd-aa43-b0f699fec09b-image.png
本文档将基于以下软、硬件环境,介绍如何实现Fast wakeup,并在最后对比Fast wakeup和Normal Mode的启动时间差异。
此处Fast wakeup功能通过修改Secure_Boot_Demo工程实现。
c150c265-42f4-49d5-b7b6-11a879a0c90f-image.png
具体操作步骤:
1.在YTLINK中划分一个retention RAM分段,用于copy IVT段中的数据。注意:
本示例中,在地址0x20020000处创建了一个名为“retentionRam”的分段
968014c4-a823-4b08-8e0e-cec4a08e90b7-image.png
Tips:
若用户需要使用YCT工具对生成的hex文件进行加密处理,务必确保增加“retentionRam”分段后编译出的hex文件不包含RAM段,否则YCT工具无法对hex文件进行加密。具体实现方式——
GCC环境:配置分段的noload属性即可
4a497de6-1180-4aca-801b-2cba944a9b54-image.png
Keil环境:YT-link中配置的noload属性对keil环境无效,使用Keil的用户可参考论坛帖解决
https://forum.ytmicro.com/topic/607/b1md-mcal-dio例程生成的hex文件为什么有0x1fff8400地址的信息?_=1753772506639
2.向REGFILE->DR[0]写入快速唤醒Tag,0x5A5B6E6F
/* Set fast wakeup tag at REGFILE->DR[0] */ REGFILE->DR[0] = 0x5A5B6E6F;3.向REGFILE->DR[1]写入预计放入IVT数据的地址,此处应当填入"retentionRam"分段的起始地址0x20020000
/* Set address of IVT table at REGFILE->DR[1], must be retention RAM area, and must be 1K algined */ REGFILE->DR[1] = 0x20020000;4.copy一份IVT区域的数据存放到"retentionRAM"分段区域
#define FLASH_IVT_ADDR 0x2000800 __attribute__((section(".retentionRam"))) uint8_t Retention_IVT[1024]; /* Copy IVT table to the address which is set at REGFILE->DR[1] */ const uint8_t* pflash_ivt_src = (const uint8_t*)FLASH_IVT_ADDR; memcpy(Retention_IVT, pflash_ivt_src, 1024); 2.2 Fast wakeup功能测试 2.2.1 测试方式如下图,编辑Secure_Boot_Demo工程,通过EN_FAST_WAKEUP宏控制开启fast wake up功能,通过观测PTB12电平变化确认是否成功启动。
b474e4d3-7edf-4b6e-aa13-2915fc482f83-image.png
1.下载并运行Secure_Boot_Prepare的demo工程,将密钥烧录到HCU_Nvr中。
2.编译Secure_Boot_Demo工程,将编译生成的hex文件上传到YCT配置工具中加密,将加密后生成的.bin文件烧录到MCU中,掉电,再重新上电,即可观察到PTB12在反复翻转(如下图),证明MCU可以成功启动。
4f157c9f-c5ad-4fa6-8635-bf9aa2d86c5e-image.png
93dc0db0-6b39-487c-8241-46a0fc651d71-image.png
在该演示示例中,需要说明:
通过控制EN_FAST_WAKEUP宏来切换Fast wakeup和Normal Boot两种启动模式,测量两种模式对应的启动时间。PTB12的低电平持续时间即为相邻两次调用软件复位函数SystemSoftwareReset函数的时间。
Fast wakeup:7.75ms
8220ceb9-67ed-4401-b507-1802fd8ff439-image.png
Normal Boot:8.46ms
f606ee82-2671-4d3d-a66f-d78d99071eb2-image.png
以上,可以看出Fast wakeup与Normal Boot启动时间上的差异,二者相差0.71ms,差异不大。
这是因为Secure_Boot_Demo工程校验的flash区域较小,若校验的范围较大,这个时间差异会更明显。
HA01_Secureboot__FastWakeup_demo.zip
数据断点(Data Breakpoint) 是断点的一种类型,用于监控内存地址及其数据的变化,而不是像普通断点那样仅关注代码执行的位置。
数据断点依赖于MCU的硬件调试模块DWT(Data Watchpoint and Trace),因此并非所有MCU都支持这一特性,其支持的个数也不一样。 Ozone数据断点操作下面以YTM32B1MD1的GPIO_Interrupt_Demo工程举例:
使用数据断点观察gpioIrqCount在何时被修改:
PixPin_2025-05-26_17-20-25.gif
详细解释如下:
3a5263bd-0fff-42a1-b3e8-e0bc43cab273-image.png f1208a40-f317-4c34-aae5-bc8824f93ad1-image.png
e57dd71b-833e-434a-a2f4-07f3c33fb6b4-image.png 常见应用场景 调试被应用程序异常破坏的标志或变量 调试堆栈溢出,可以在堆栈栈顶接近栈大小的位置打数据断点 数据断点的地址可以是外设寄存器的地址,可以调试外设寄存器被误修改的场景 注意事项 数据断点对于“DMA对内存的修改”无效 数据断点对于“Debugger对内存的修改”无效
Config Tool Version:2.7.6
SDK version:1.3.1
IDE:IAR
509cab12-ec71-4a79-94fa-46ba72a33aec-image.png 2.2 RAM 第一阶段初始化(RamInit0) /* RamInit 0 Stage, focus on ecc init, asm code*/ BL RamInit0 SRAM存储器中的内容在上电之后内容是随机的,其中的有效数据和ECC数据并未建立起关联。此时,如果读取SRAM的内容并进行ECC校验,大概率上是会出现ECC错误的。 在使用支持ECC的SRAM之前,需要手动对SRAM进行初始化操作(循环赋值0x5A,方便辨认)。 另外YT_LINK中的RAM段的POR_ONLY属性就是在RamInit0和RamInit1中完成。读取RCU上电标志位,以判断是否执行这段RAM的初始化。(例如开辟一段空间存放Bootloader和APP的交互信息)
3f3feff0-4279-44d2-b615-cc75694a58e9-image.png 2.3 设置栈顶指针(SP) /* Initialize the stack pointer */ LDR r0,=STACK_end MOV r13,r0 栈是 C 语言运行的基础(用于函数调用、局部变量存储等)。STACK_end是栈的栈顶地址(由链接脚本定义,栈通常向下生长,即高地址向低地址生长)。 此步骤为后续 C 函数调用(如RamInit1)准备栈环境。 2.4 RAM 第二阶段初始化(RamInit1) /* RamInit 1 Stage, focus on copy data,clear bss, c code*/ LDR r0,=RamInit1 BLX r0 注释:RamInit1,用于复制数据段(.data)、清除 BSS 段(未初始化全局变量),由 C 语言实现。 RamInit0是将RAM初始化为统一固定值0x5A,而RamInit1则是将定义在RAM中的全局变量初始化赋值。 有初始值的定义在(.data段),初始化是从FLASH将初始值copy到RAM。另外如果设置了POR_ONLY属性的RAM段在无上电标志位时则不会copy;设置INIT_NULL属性的RAM也不会copy。
0c6e1538-f689-4e24-bcf1-8f7973b19b15-image.png 定义了但未赋值的全局变量则会定义在(.bss)段,会被清零。
e59e886d-f82b-4d7b-965c-5389a005b219-image.png 2.5 复制中断向量表 /* Copy Vector Table for interrupt, c code */ #ifndef __NO_VECTOR_TABLE_COPY /* Call the to copy vector table from flash to ram */ ldr r0,=VectorTableCopy blx r0 #endif
19e38303-1188-4187-a36d-0da6f0eecb6a-image.png
作用:中断向量表(存储各中断处理函数地址)默认存储在 Flash 程序的起始地址,复制到 RAM 可提高中断响应速度,或支持动态修改向量表。 将中断向量表基地址(SCB->VTOR)偏移到 IVT_RAM_start(由链接脚本定义); 中断向量表在链接脚本中默认1024Byte空间,在程序的起始地址,第一个字是栈顶指针,第二个字就是Reset_Handle的地址,后面是所有中断的地址入口。中断向量表在Vector.s中定义。 可通过宏 __NO_VECTOR_TABLE_COPY 配置是否需要 VectorTableCopy。07653add-7bcd-4fce-8fb8-82782edfe7b4-image.png
fae1ce37-c753-4d4d-9797-b2a120308a74-image.png 2.6 系统初始化 #ifndef __NO_SYSTEM_INIT LDR r0,=SystemInit BLX r0 ; 调用SystemInit #endif 云途不同芯片的系统初始化内容有些许差异,以HA0为例,会使能FPU(浮点运算单元),Flash的Deep PowerDown Enable,关闭WDG。 可通过宏 __NO_SYSTEM_INIT 配置是否需要 SystemInit。
bb181722-3454-48b7-8e24-3095e246aca2-image.png 2.7 RAM 第三阶段初始化(RamInit2) /* RamInit 2 Stage, focus on others ram init, c code */ LDR r0,=RamInit2 BLX r0 作用:处理前两阶段未包含的 RAM 初始化需求(如特殊用途 RAM),由C语言实现。 如图RamInit2为一个弱函数,用户可以重写(覆盖) 这个函数。
3354cdbc-5dbd-4b62-8aaa-328bdc5ab0b1-image.png 2.8 开启中断,跳转至main /* Unmask interrupts */ CPSIE I /* Call the main routine */ BL main 开启 IRQ 中断,为进入main函数做准备 BL main:跳转到 C 语言的main函数,启动应用程序。 2.9 死循环(main返回后) JumpToSelf: B JumpToSelf END 若main函数意外返回(正常情况下main不会返回),程序会进入死循环,防止跑飞(执行未知地址指令)。 2.10 总结 该启动文件的核心流程是:复位后关闭中断 → 初始化通用寄存器组 → 分阶段初始化 RAM(含 data段 / BSS、扩展 RAM) → 设置栈 → 复制向量表 → 系统初始化 → 跳转至main。整个过程为 C 程序运行准备了硬件环境(RAM、WDG、Flash、中断向量、FPU等等)和软件环境(栈、全局变量),是从硬件复位到应用程序启动的桥梁。 3. 不同型号芯片启动时间
优化等级:Low
基于Helloword demo程序测试:
db770b96-8d52-46d7-a687-6da907646f07-image.png
d4010816-923a-4fee-86ef-85d6e9446732-image.png
LE1:45acf8f4-1e35-4274-8972-6db1273a9fed-image.png
MC0:06bf7614-b73c-44a2-871f-e978af156664-image.png
MD1:96ef18f9-c380-4b3a-a730-eea2f646dc70-image.png
MD2:0a3beceb-2038-49e0-80d2-3a539c68c3c4-image.png
ME0:0bef586e-e34b-47c6-8b51-e9e30ef121b9-image.png
HA0:40cd4029-aa9c-451e-a100-ecf1c622455a-image.png
tips:
d188e5e7-1584-4454-a934-6e747ee5c2a7-image.png
如上图在每一段RAM赋初值0x5A的前面加上ALIGNROM 4,确保后续代码 / 数据地址满足 4 字节对齐,提高访问正确性和效率。 4.2 RamInit1优化如下图,使用C语言标准库函数memcopy,和memset代替RAMInit1的循环赋值操作,汇编优化更好:
3adeb124-7ac4-4598-bcc3-b25706d6b0b1-image.png
d8063910-647c-4b06-b593-9e6fb59ffa8b-image.png
4.3 减少RAM初始化 可通过YCT去配置RAM段的Init_Policy属性为NULL,这样就不会初始化这段RAM,当然为了防止RAM_ECC,也不能访问这段RAM,可在正常启动后重新以32bit为单位(ECC机制)向这段RAM写入初始值,就可以正常访问了。 这种方法适用于对RAM需求量小的工况,例如powerdown周期性唤醒,唤醒复位后只需执行少量代码就继续进入powerdown。1bc02a7f-7f29-4295-970b-e35b74909e56-image.png 4.4 打开I-Cache(HA,MD2)
b84ed9fc-2c7f-4d3f-a2e6-fb50a25110f9-image.png
HA(M7内核)和MD2系列,也可以打开I-Cache,对于反复用到的指令,比如循环赋值指令,打开I-Cache可提高指令命中率,避免反复访问Flash取指令降低效率。
在启动文件打开I-Cache参考下图代码(HA),可在进入main函数后关闭I-Cache。
a20cd4e7-8823-48bf-aee5-c948b2a972f0-image.png
03d570eb-894e-434b-af2c-207b353f316f-image.png
-
Announcements
Announcements regarding our community
-
Discussion & Question
A place to talk about whatever you want or ask a question
-
Blogs
Blog posts from individual members
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...