硬汉哥和各位网友好,有个问题咨询一下,自己由于工作原因,制作了一个离线烧录器。用来对产线产品进行批量烧录。使用的是GPIO模拟SWD协议,在之前开发F1、F4、U575的时候都是没问题的。最近想尝试制作H750版本的时候出了问题。
由于H750的FLASH是带ECC校验的,不知道该怎么写FLASH了。
以前M33内核U575的烧录的代码如下,是能够正常写入到单片机的FLASH的。
[C] 纯文本查看 复制代码 for( u32 tmp11 = 0;tmp11 < HowMany4K; tmp11++ ) // 写Flash的操作,每次操作8K字节
{
u32 Address = userfile.ProgramStartAddress + tmp11 * 0x1000; // 起始操作地址
W25QXX_Read( &stm32u5xx_flash_8k_tmp.IndexLen8[0] , userfile.ProgramSaveAtW25QAddress + tmp11 * 0x1000, 0x1000); // 4k大小在16进行下,就是0x1000
writeAP( AP_CSW,0x43000012 ); // 长度为32bit,同时地址自动增加
writeAP( AP_TAR, Address ); // 要写入到FLASH上的地址!
for( u32 tmp12 = 0;tmp12 < 0x1000; tmp12 += 4 ) // 写入4K,理论上brust模式每次可以写入8个4字,共128个字节,但是实测可以一直写,可能大文件需要在写入128个字节后去读取NSSR寄存器状态
{
#define SWD_AUTO_ADDRESS_ADD_VALUE 0x400 // 特别警告:STM32U5系列的地址自增大小为1024个
if( ((Address + tmp12) % SWD_AUTO_ADDRESS_ADD_VALUE) == 0 ) // 说明到了1k临界点,需要重新写地址
{
writeAP( AP_TAR, Address + tmp12 ); // 地址!
}
writeAP(AP_DRW, stm32u5xx_flash_8k_tmp.IndexLen32[tmp12 / 4]);
}
{ // 程序进度区!程序进度是8K大小!
unsigned int tmp13 = 50 * (tmp11 + 1) / HowMany4K;
ESP32_lvgl_mutex_lock();
lv_bar_set_value(guider_ui.screen_3_bar_1,tmp13,LV_ANIM_ON); //写入和校验各占50%进度条
ESP32_lvgl_mutex_unlock();
ESP_LOGI(TAG_DOWNLOAD,"the chip is programed %d %%...",(uint8_t)tmp13);
}
vTaskDelay(pdMS_TO_TICKS(1)); //在此处增加一个延时,以免占用线程太久,造成的速度损失测量后再确定
}
下面是具体的疑惑
一、使用上述的逻辑,对H750的FLASH进行写入,发现写进去的全是0.

二、用数据分析仪监控了一下STLINK是如何写入的,发现STLINK并不是直接将bin文件写入到内置0x08000000地址,而是直接将bin文件先写入到AXI_RAM中,好奇怪,这个地方难道是用上了AXI_RAM自带的ECC校验功能?
因为STLINK的协议过程很长,还没具体分析出在写入FLASH之前,是不是对AXI_RAM进行了一些设置。这个地方需要重点排查。
三、当时已经没头绪了,所以就看了一下HAL库中是如何写FLASH的,发现HAL库文件在定义FLASH写入的时候是一次性固定写进去32个字,也就是256bit,这个和手册上描述的是相符的,256bit配10bit的ECC校验位。所以我想问一下,在FLASH写入256bit内容后,增加的10个bitECC校验位是在隐藏的FLASH区域内吗?还是说我写入256bit,那FLASH区域就直接减少266bit?下面的代码可以看到单次固定写8*4=32个字节
[C] 纯文本查看 复制代码 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
{
HAL_StatusTypeDef status;
__IO uint32_t *dest_addr = (__IO uint32_t *)FlashAddress;
__IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
uint32_t bank;
uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
/* Check the parameters */
assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));
/* Process Locked */
__HAL_LOCK(&pFlash);
#if defined (FLASH_OPTCR_PG_OTP)
if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
#else
if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
#endif /* FLASH_OPTCR_PG_OTP */
{
bank = FLASH_BANK_1;
/* Prevent unused argument(s) compilation warning */
UNUSED(TypeProgram);
}
#if defined (DUAL_BANK)
else if(IS_FLASH_PROGRAM_ADDRESS_BANK2(FlashAddress))
{
bank = FLASH_BANK_2;
}
#endif /* DUAL_BANK */
else
{
return HAL_ERROR;
}
/* Reset error code */
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
if(status == HAL_OK)
{
#if defined (DUAL_BANK)
if(bank == FLASH_BANK_1)
{
#if defined (FLASH_OPTCR_PG_OTP)
if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
{
/* Set OTP_PG bit */
SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
}
else
#endif /* FLASH_OPTCR_PG_OTP */
{
/* Set PG bit */
SET_BIT(FLASH->CR1, FLASH_CR_PG);
}
}
else
{
/* Set PG bit */
SET_BIT(FLASH->CR2, FLASH_CR_PG);
}
#else /* Single Bank */
#if defined (FLASH_OPTCR_PG_OTP)
if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
{
/* Set OTP_PG bit */
SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
}
else
#endif /* FLASH_OPTCR_PG_OTP */
{
/* Set PG bit */
SET_BIT(FLASH->CR1, FLASH_CR_PG);
}
#endif /* DUAL_BANK */
__ISB();
__DSB();
#if defined (FLASH_OPTCR_PG_OTP)
if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
{
/* Program an OTP word (16 bits) */
*(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
}
else
#endif /* FLASH_OPTCR_PG_OTP */
{
/* Program the flash word */
do
{
*dest_addr = *src_addr;
dest_addr++;
src_addr++;
row_index--;
} while (row_index != 0U);
}
__ISB();
__DSB();
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
#if defined (DUAL_BANK)
#if defined (FLASH_OPTCR_PG_OTP)
if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
{
/* If the program operation is completed, disable the OTP_PG */
CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
}
else
#endif /* FLASH_OPTCR_PG_OTP */
{
if(bank == FLASH_BANK_1)
{
/* If the program operation is completed, disable the PG */
CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
}
else
{
/* If the program operation is completed, disable the PG */
CLEAR_BIT(FLASH->CR2, FLASH_CR_PG);
}
}
#else /* Single Bank */
#if defined (FLASH_OPTCR_PG_OTP)
if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
{
/* If the program operation is completed, disable the OTP_PG */
CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
}
else
#endif /* FLASH_OPTCR_PG_OTP */
{
/* If the program operation is completed, disable the PG */
CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
}
#endif /* DUAL_BANK */
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
之前看硬汉哥的H7TOOL是支持离线烧录的,所以想咨询一下,如果不使用烧录算法,使用SWD模拟的情况下,该如何处理带ECC校验的FLASH写入。谢谢。
|