stm32L4xx 通过USB DFU功能升级固件背景 因为项目需求,用户不方便用SWD模式下载程序,而且本设备也留有USB,因此考虑用USB DFU模式进行固件升级。
设备上使用的单片机是stm32l476,ST官方在单片机内部bootloader已经支持通过USB方式升级固件,但是需要通过修改MODE来切换是升级固件还是运行用户程序,设备本身也没有留修改mode的按键等,因此考虑修改使用USB DFU实现的IAP功能。 设计思路设备上电后,5秒内没有检测到USB,那么进入用户程序区,如果检测到USB插入,进入Bootloader,等待下载固件。 实现步骤- USB DFU Bootloader代码
基本上完全使用了STM32Cube库中的例子,只是在它的基础上稍微做了修好,加入了usb是否插入的状态读取。
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] SetupStage callback.
* @param hpcd: PCD handle
* @retval None
*/
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
/*监测到USB插入后,亮绿灯,并且把标志位置1*/
BSP_LED_On(LED_GREEN);
usb_dfu_is_activated = 1;
USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup);
}
/*main 函数*/
int main(void)
{
/* Initialize the HAL Library */
HAL_Init();
/* Configure the system clock to 80 MHz */
SystemClock_Config();
/* Enable Power Clock*/
__HAL_RCC_PWR_CLK_ENABLE();
/* enable USB power on Pwrctrl CR2 register */
HAL_PWREx_EnableVddUSB();
/* Configure LED1, LED2, LED3 and LED4 */
BSP_LED_Init(LED_GREEN);
/* Otherwise enters DFU mode to allow user programing his application */
/* Init Device Library */
USBD_Init(&USBD_Device, &DFU_Desc, 0);
/* Add Supported Class */
USBD_RegisterClass(&USBD_Device, USBD_DFU_CLASS);
/* Add DFU Media interface */
USBD_DFU_RegisterMedia(&USBD_Device, &USBD_DFU_Flash_fops);
/* Start Device Process */
USBD_Start(&USBD_Device);
//等待5s
HAL_Delay(5000);
if(usb_dfu_is_activated == 1){
/* Run Application (Interrupt mode) */
while(1){
}
}
else{
// /* Test if user code is programmed starting from address 0x0800C000 */
if(((*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000 ) == 0x20000000)
{
//把USB停止掉,否则当用户程序运行后,插上USB也会检测到,但是是没有识别的USB设备
USBD_Stop(&USBD_Device);
USBD_DeInit(&USBD_Device);
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD);
JumpToApplication();
}
}
while(1){
}
}
|