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在使用 LE0 SDK 1_4_0 HOTFIX_001 的 FLASH_DRV_Program 接口时发现一个问题。请问除了使用断言,是否有其他方式预防客户,调用时出现HardFault?因为客户基本没开断言
问题现象:
列表当传入的 pData 地址非 4 字节对齐时,程序会触发 HardFault (Unaligned Access)。原因分析:
列表该接口原型定义为 const void * pData,但在内部实现中,直接将其强转为 uint32_t * 使用(源码中带有 /* PRQA S 0316 */ 注释)。由于 void * 允许任意地址,当应用层传入非对齐地址时,这种强转会导致在访问时,HardFault。 status_t FLASH_DRV_Program(..., const void * pData) { // 强转发生处,PRQA 警告被屏蔽 state->cmdParam.pdata = (const uint32_t *) pData; /* PRQA S 0316 */ // ... } static status_t FLASH_LaunchCommandSequence(uint32_t instance) { // ... // 在此处触发 Unaligned Access HardFault for (uint32_t i = 0; i < state->cmdParam.word_size; i++) { state->cmdParam.dest[i] = state->cmdParam.pdata[i]; } // ... }
Config Tool Version:2.7.6
IDE:GCC+VSCode
在调查分析低功耗问题时,可以将下面对应的elf文件下载到板子上进行功耗测试。
如功耗比对正常,就可以快速排除芯片自身,及部分硬件电路的原因。
f18aa665-d8af-435b-9981-992492ca43b9-image.png MC0,MD24,HA01 需要将PTA10(JTAG_TDO)设置为pull-up
3c734066-eba1-42de-9b66-458c43578e6b-image.png 测试注意事项 电流表串联进芯片VDD PIN脚,不要分流其他器件。 断开仿真器。 YTM32B1LE0开发板测试需要拿掉2个滑动变阻器RP1,RP2。 YTM32B1HA0开发板测试需要拔掉J35,J36 YTM32B1LE0
70b758b4-afe6-491a-a319-25d0c53dd0ed-image.png
YTM32B1LE0_Standby_SIRC_Enable.elf
YTM32B1LE0_Standby_SIRC_Disable.elf
YTM32B1LE0_Standby.zip
63a82db6-5051-47ab-b533-9820fa1f5cdf-image.png
YTM32B1LE1_Standby_SIRC_Enable.elf
YTM32B1LE1_Standby_SIRC_Disable.elf
YTM32B1LE1_Standby.zip
b793ad60-3863-45a0-9f9d-17f74b9f8174-image.png
YTM32B1MC0_Standby_SIRC_Disable.elf
YTM32B1MC0_Standby_SIRC_Enable.elf
YTM32B1MC0_Standby.zip
6c917447-85d9-40c8-8b8e-f0d24f40aa01-image.png
YTM32B1MD1_PowerDown_SIRC_Disable.elf
YTM32B1MD1_PowerDown_SIRC_Enable.elf
YTM32B1MD1_StandBy_SIRC_Disable.elf
YTM32B1MD1_StandBy_SIRC_Enable.elf
YTM32B1MD1_PowerDown.zip
7817f175-04da-4eaa-8be8-fd6aa3560b12-image.png
YTM32B1MD2_Standby_SIRC_Disable.elf
YTM32B1MD2_Standby_SIRC_Enable.elf
YTM32B1MD2_Standby.zip
92576185-4334-4d16-8f06-ca62541002ae-image.png
YTM32B1ME0_PowerDown_SIRC_Disable.elf
YTM32B1ME0_PowerDown_SIRC_Enable.elf
YTM32B1ME0_StandBy_SIRC_Disable.elf
YTM32B1ME0_StandBy_SIRC_Enable.elf
YTM32B1ME0_PowerDown.zip
19e00a5b-7ccb-42d1-ab87-ac0b6a8281dd-image.png
YTM32B1HA0_PowerDown_SIRC_Disable.elf
YTM32B1HA0_PowerDown_SIRC_Enable.elf
YTM32B1HA0_StandBy_SIRC_Disable.elf
YTM32B1HA0_StandBy_SIRC_Enable.elf
YTM32B1HA0_PowerDown.zip
82f66f21-ce70-42c7-bd12-0bc1f923596a-image.png
YTM32Z1LS0_Standby_SIRC_En.elf
YTM32Z1LS0_Standby_SIRC_Dis.elf
YTM32Z1LS0_PowerDown.elf
措施: 在睡眠之前把不需要工作的外设Disable,其外设中断Disable; 在唤醒以后吧需要工作的外设重新Enable,其外设中断Enable;
demo工程:
MC0_MID_DEMO.zip
背景
解决方案描述
采用双通道协同的工作方式: 通道2(eTMR_CH2):配置为PWM输出模式 通道5(eTMR_CH5):配置为输出比较模式,用于产生周期中点中断 用周期中点中断作为同步基准点,在当前PWM周期运行至一半时,更新下一个完整周期的PWM参数,实现动态调整
步骤
ETMR模块配置
PWM输出通道选择CH2,频率为10000HZ
37a4ae3d-3db7-4e8f-b31e-3bb322a078d7-image.png
Output Compare通道选择CH5
时钟源为FXOSC(24000000HZ)
设置初始VAL0 VAL1值为 (240000000/100000)/2 = 1200
51ead5b4-bac1-4f86-ba96-293b24ce3749-image.png
代码
这两个数组定义了一组PWM周期及其对应的中断触发点:
// PWM周期值(计数器计数值)
uint32_t eTMR_values[] = {10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000};
// 对应的中断触发点(周期一半的计数值)
uint32_t values[] = {2400, 2667, 3000, 3429, 4000, 4800, 6000, 8000, 12000, 24000}; /* USER CODE BEGIN Header */ /* you can remove the copyright */ /* * Copyright 2020-2023 Yuntu Microelectronics Co., Ltd. * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * * @file main.c * @brief * */ /* USER CODE END Header */ #include "sdk_project_config.h" /* Includes ------------------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "osif.h" #include <stdint.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define ETMR_INST 0 #define ETMR_CHANNEL_INDEX0 2 #define ETMR_CHANNEL_INDEX1 3 volatile uint8_t i = 0; uint32_t eTMR_values[] = { 10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000 }; uint32_t values[] = { 2400, // 10000 -> 2400 2667, // 9000 -> 2667 3000, // 8000 -> 3000 3429, // 7000 -> 3429 4000, // 6000 -> 4000 4800, // 5000 -> 4800 6000, // 4000 -> 6000 8000, // 3000 -> 8000 12000, // 2000 -> 12000 24000 // 1000 -> 24000 }; /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function declare --------------------------------------------------*/ /* USER CODE BEGIN PFDC */ /* USER CODE END PFDC */ static void Board_Init(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void eTMR0_Ovf_IRQHandler(void) { eTMR_DRV_ClearTofFlag(0); } void eTMR0_Ch4_Ch5_IRQHandler(void) { /* Clear interrupt flag */ eTMR_DRV_ClearChnFlag(0, 1 << 5); if(i <= 10) { PINS_DRV_TogglePins(GPIOD, (1<<5)); eTMR_DRV_UpdatePwmPeriod(ETMR_INST, ETMR_CHANNEL_INDEX0, eTMR_values[i]); eTMR0->CH[5].VAL0 = values[i] / 2; eTMR0->CH[5].VAL1 = values[i] / 2; eTMR_DRV_SetLdok(ETMR_INST); i++; } else i = 100; /* Add your code here */ } /* 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 */ /* PWM is generated when eTMR enable, the duty cycle is configured in the initial function */ INT_SYS_EnableIRQ(eTMR0_Ch4_Ch5_IRQn); eTMR_DRV_Enable(ETMR_INST); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } static void Board_Init(void) { CLOCK_SYS_Init(g_clockManConfigsArr,CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr,CLOCK_MANAGER_CALLBACK_CNT); if(STATUS_SUCCESS != CLOCK_SYS_UpdateConfiguration(CLOCK_MANAGER_ACTIVE_INDEX,CLOCK_MANAGER_POLICY_AGREEMENT)) { /* USER CODE BEGIN ERROR_HANDLER 1 */ SystemSoftwareReset(); /* USER CODE END ERROR_HANDLER 1 */ } PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0,g_pin_mux_InitConfigArr0); eTMR_DRV_Init(0,&ETMR_CM_Config0,&ETMR_CM_Config0_State); eTMR_DRV_InitPwm(0,&ETMR_PWM_Config0); eTMR_DRV_InitOutputCompare(0,&ETMR_OC_Config0); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */
基于MD这类没有独立Dflash的MCU,且同时具有硬件AB swap需求和FEE历史数据保持的需求,优先建议客户选择外挂的eeprom,硬件方案实在无法外挂eeprom再参考该文档实现,本文档是基于MD14开发板设计的。
2.FLASH分区划分d3d3046e-3140-461d-8cc9-9ab07d7a1786-image.png
FLASH的分区主要分为两种:一种是将程序和fee各自存放在一个BANK上,另一种是将程序和fee存放在同一个BANK上。由于在同一个bank下flash在写一个区域的同时不能读取另外一个区域的特性,所以如果将程序与fee存放在同一个bank下,当对fee进行操作时就不能运行其他的进程,所以默认情况下是将程序与fee存放在不同的bank,这样就引出了fee的“数据同步”和“异步操步”。
在不同的物理 BLOCK 上的 FLASH 程序和数据可支持异步操作不产生阻塞;在相同的物理 BLOCK 上的 FLASH 程序和数据只支持同步操作会产生阻塞。所以我们一般将fee地址设置在另一个block上,勾选"Async Access"代表使能异步操作
555bf04b-7914-4356-ab76-8554074ab65b-image.png
在执行AB swap操作前PFLASH0的地址是0x00000 ~ 0x3FFFF,PFLASH1的地址是0x40000 ~ 0x7FFFF。在执行AB swap操作后,PFLASH0和PFLASH1的地址会进行交换,此时PFLASH0的地址是0x40000 ~ 0x7FFFF,PFLASH1的地址是0x00000 ~ 0x40000。但与此同时原先定义在另一个bank里的fee区域,由于执行了boot_swap命令,定义的fee地址发生了改变,这是就引出了fee的“数据同步”
fbf61dc9-5884-4fbc-a77b-99f8a756f1fa-image.png
在实际的应用中,我们存储在fee区域的数据是要经常调用使用的,如果不进行数据同步,在执行完swap命令后,我们再去调用fee数据就会导致读出的数据为空,所以数据同步是在执行boot swap命令前要将fee数据搬运到新的fee地址上去。
d5552a13-f9ee-441c-a411-c1eb90ac378a-image.png
通过内部闪存命令(0x30)执行swap操作。该命令由FLASH_DRV_BootSwap函数来调用。
56f41337-90fa-49be-ae8f-aae8d1daccbc-image.png
boot_swap是在pFlash0 和 pFlash1 之间进行翻转,通过查看EFM->STS的寄存器判断现在运行在哪个pFlash上
f2331418-b1ae-4251-a9ec-6a5bb295679d-image.png
Config Tool Version:2.7.6
MD14 SDK version:1.3.1
读取swap标志位,从而判断代码运行在哪个PFLASH里
42c0a859-d355-4013-a917-1beb71532349-image.png
读取REGFILE->DR[0]的值,写入到fee并反读(REGFILE 位于始终处于供电状态的电源域中,可在掉电模式下保留某些关键信息的值。)
e6250638-b10a-4a63-a804-211aa8a62edd-image.png
验证写入和读取是否相同,如果不同则进入死循环
383102f6-45bf-48a2-9e1b-f3e796465b99-image.png
在进行swap操作前将fee数据搬移到新的fee地址里去
cf7f5a80-b4f4-4041-9428-d087e8e8dfab-image.png
2b97bb14-8d22-4380-980c-35b308f136df-image.png
5.2 擦除芯片,烧录程序(快捷键盘F4,F6),完成PFLASH0面烧录8983da7f-109c-4a9e-bec8-7d4f678dd226-image.png
47b8b895-437d-4891-9151-c49714c4f03c-image.png
36f6dccf-ad62-435d-b2d2-29d499d52fad-image.png
5.3.2 设置地址偏移74506f56-98ef-4176-902d-1f90b0649e69-image.png
792dc419-3535-4f90-a7f4-5c01f9a41b58-image.png
f02d0e99-8cb9-496d-a0e6-16fb6052b1b0-image.png
5.3.4 重新上电运行程序 PFLAH0里的程序会使绿灯亮红灯灭,PFLASH1里的程序会使绿灯灭红灯亮 程序会在红灯和绿灯之间来回切换(绿灯代表运行在PFLASH0里,红灯代表运行在PFLASH1里) 红灯和绿灯切换的频率800ms切换一次 串口会在打印程序运行在哪个位置508539c7-eec9-4a0a-9be4-59bfb1335afd.jpg fc41ac20-56c1-466b-8d65-7b36561ceadc.jpg
串口打印的数据
fbf6d032-520c-4d60-9e81-7d99d772bff1-image.png 4.4 压测10000次数据
fee_data.txt
5. 代码AB_SWAP_FEE.zip
-
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哦...