diff --git a/Makefile b/Makefile index 759d531..3057473 100644 --- a/Makefile +++ b/Makefile @@ -179,6 +179,7 @@ FWTARGETS += stm32l433xb stm32l433xc FWTARGETS += stm32f070x6 stm32f070xb stm32f072x8 FWTARGETS += stm32g431x6 stm32g431x8 stm32g431xb FWTARGETS += stm32g474xb stm32g474xc stm32g474xe +FWTARGETS += stm32g491xe stm32g491xc stm32g4a1xe stm32g4a1xc FWTARGETS += stm32f446xc stm32f446xc_hs stm32f446xe stm32f446xe_hs FWTARGETS += stm32f405xg stm32f405xg_hs @@ -555,6 +556,30 @@ stm32g474xe : FWDEFS='STM32G4 STM32G474xx USBD_ASM_DRIVER' \ LDPARAMS='ROMLEN=512K RAMLEN=96K APPALIGN=0x1000' +stm32g491xe : + ${MAKE} bootloader FWCPU='-mcpu=cortex-m4' \ + FWSTARTUP='mcu/stm32g4xx.S' \ + FWDEFS='STM32G4 STM32G491xx USBD_ASM_DRIVER' \ + LDPARAMS='ROMLEN=512K RAMLEN=96K APPALIGN=0x4000' + +stm32g491xc : + ${MAKE} bootloader FWCPU='-mcpu=cortex-m4' \ + FWSTARTUP='mcu/stm32g4xx.S' \ + FWDEFS='STM32G4 STM32G491xx USBD_ASM_DRIVER' \ + LDPARAMS='ROMLEN=256K RAMLEN=96K APPALIGN=0x4000' + +stm32g4a1xe : + ${MAKE} bootloader FWCPU='-mcpu=cortex-m4' \ + FWSTARTUP='mcu/stm32g4xx.S' \ + FWDEFS='STM32G4 STM32G491xx USBD_ASM_DRIVER' \ + LDPARAMS='ROMLEN=512K RAMLEN=96K APPALIGN=0x4000' + +stm32g4a1xc : + ${MAKE} bootloader FWCPU='-mcpu=cortex-m4' \ + FWSTARTUP='mcu/stm32g4xx.S' \ + FWDEFS='STM32G4 STM32G491xx USBD_ASM_DRIVER' \ + LDPARAMS='ROMLEN=256K RAMLEN=96K APPALIGN=0x4000' + stm32f446xc : $(MAKE) bootloader FWCPU='-mcpu=cortex-m4' \ FWSTARTUP='mcu/stm32f4xx.S' \ diff --git a/README.md b/README.md index 74ff8e5..66662e7 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,8 @@ The bootloader can be configured through the make parameters. See CONFIG.md for | stm32g474xb | STM32G471xB, STM32G473xB, STM32G474xB, STM32G483xB | | | stm32g474xc | STM32G471xC, STM32G473xC, STM32G474xC, STM32G483xC | | | stm32g474xe | STM32G471xE, STM32G473xE, STM32G474xE, STM32G483xE | tested G747RE | +| stm32g491xe | STM32G491xE, STM32G4A1xE | +| stm32g491xc | STM32G491xC, STM32G4A1xC | | stm32f303xe | STM32F303xE | tested | | stm32f373xc | STM32F373xC | tested | diff --git a/config.h b/config.h index 6f6577c..b452502 100644 --- a/config.h +++ b/config.h @@ -115,8 +115,15 @@ #define DFU_DSC_FLASH _ENABLE #endif #ifndef DFU_STR_FLASH +#if defined(STM32G491xx) //Cat4 +// NB: overstated for STM32G4x1xc which is only 256K +#define DFU_STR_FLASH "Internal flash/0x08000000/256*2KE" +#elif defined(STM32F429xx) +#define DFU_STR_FLASH "Internal flash/0x08000000/4*16KE,1*64KE,6*128KE,4*16KE,1*64KE,6*128KE" +#else #define DFU_STR_FLASH "Internal flash" #endif +#endif /* USB string for DFU EEPROM interface sreing descriptor */ #ifndef DFU_DSC_EEPROM #define DFU_DSC_EEPROM _ENABLE @@ -128,14 +135,22 @@ #define DFU_EP0_SIZE 8 /* DFU properties */ #ifndef DFU_POLL_TIMEOUT +#if defined(STM32G491xx) //Cat4 +#define DFU_POLL_TIMEOUT 50 +#else #define DFU_POLL_TIMEOUT 20 #endif +#endif #ifndef DFU_DETACH_TIMEOUT #define DFU_DETACH_TIMEOUT 200 #endif #ifndef DFU_BLOCKSZ +#if defined(STM32G491xx) //Cat4 +#define DFU_BLOCKSZ 0x800 +#else #define DFU_BLOCKSZ 0x80 #endif +#endif /* 32 bit DFU bootkey value */ #ifndef DFU_BOOTKEY #define DFU_BOOTKEY 0x157F32D4 diff --git a/mcu/stm32g4xx.S b/mcu/stm32g4xx.S index 0d50c06..8e04441 100644 --- a/mcu/stm32g4xx.S +++ b/mcu/stm32g4xx.S @@ -326,6 +326,10 @@ program_flash: /* calculating PNB[6:0]: ADDR[17:11] -> CR[9:3] */ lsrs r4, 11 bfi r5, r4, 3, 7 +#elif defined(STM32G491xx) //Cat4 +/* calculating PNB[7:0]: ADDR[18:11] -> CR[10:3] */ + lsrs r4, 11 + bfi r5, r4, 3, 8 #else // Cat3 /* check dual bank */ ldr r5, [r3, FLASH_OPTR] diff --git a/src/bootloader.c b/src/bootloader.c index 6299daf..c9c5fee 100644 --- a/src/bootloader.c +++ b/src/bootloader.c @@ -74,6 +74,9 @@ static struct dfu_data_s { uint8_t interface; uint8_t bStatus; uint8_t bState; +#if defined(DFU_WATCHDOG) + uint32_t counter; +#endif } dfu_data; /** Processing DFU_SET_IDLE request */ @@ -100,6 +103,27 @@ static usbd_respond dfu_set_idle(void) { extern void System_Reset(void); +static inline void heartbeat(void) { +#if defined(DFU_WATCHDOG) + dfu_data.counter = 0; + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; + SysTick->VAL = SysTick->LOAD = (1ULL << 24) - 1; + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; +#endif +} + +static inline void watchdog(void) { +#if defined(DFU_WATCHDOG) + if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) { + dfu_data.counter++; + } + if ((((uint64_t)dfu_data.counter << 24) + | (~SysTick->VAL & ((1ULL << 24) - 1))) > DFU_WATCHDOG) { + System_Reset(); + } +#endif +} + static usbd_respond dfu_err_badreq(void) { dfu_data.bState = USB_DFU_STATE_DFU_ERROR; dfu_data.bStatus = USB_DFU_STATUS_ERR_STALLEDPKT; @@ -142,8 +166,33 @@ static usbd_respond dfu_dnload(void *buf, size_t blksize) { dfu_data.bState = USB_DFU_STATE_DFU_ERROR; return usbd_ack; } - aes_decrypt(buf, buf, blksize ); - dfu_data.bStatus = dfu_data.flash(dfu_data.dptr, buf, blksize); + if (blksize == 5) { + uint8_t *cp = buf; + uint8_t command = *cp; + if ((command == 0x21) /* SET_ADDRESS command */ + || (command == 0x41)) { /* ERASE_PAGE command */ + uint32_t address = cp[1] + | ((uint16_t)cp[2] << 8) + | ((uint32_t)cp[3] << 16) + | ((uint32_t)cp[4] << 24); + if (command == 0x41) { /* ERASE_PAGE command */ + *((uint64_t*)buf) = -1LL; + dfu_data.bStatus = dfu_data.flash( + (void*)(uintptr_t)address, + buf, + sizeof(uint64_t)); + } else { /* SET_ADDRESS command */ + dfu_data.dptr = (void*)(uintptr_t)address; + dfu_data.bStatus = USB_DFU_STATUS_OK; + } + blksize = 0; + } else { + dfu_data.bStatus = USB_DFU_STATUS_ERR_TARGET; + } + } else { + aes_decrypt(buf, buf, blksize); + dfu_data.bStatus = dfu_data.flash(dfu_data.dptr, buf, blksize); + } if (dfu_data.bStatus == USB_DFU_STATUS_OK) { dfu_data.dptr += blksize; @@ -223,6 +272,7 @@ static void dfu_reset(usbd_device *dev, uint8_t ev, uint8_t ep) { } static usbd_respond dfu_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) { + heartbeat(); (void)callback; if ((req->bmRequestType & (USB_REQ_TYPE | USB_REQ_RECIPIENT)) == (USB_REQ_STANDARD | USB_REQ_INTERFACE)) { switch (req->bRequest) { @@ -287,6 +337,7 @@ static usbd_respond dfu_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_ca static usbd_respond dfu_config(usbd_device *dev, uint8_t config) { + heartbeat(); switch (config) { case 0: usbd_reg_event(dev, usbd_evt_reset, 0); @@ -313,7 +364,9 @@ static void dfu_init (void) { int main (void) { dfu_init(); + heartbeat(); while(1) { usbd_poll(&dfu); + watchdog(); } }