STM32 bootloader DFU mode using CubeMX. Instructions step by step, step by step

So, the essay of this mandala was promoted by the almost complete absence of step-by-step instructions using the usual tools offered by STMicroelectronics. 3r3663.  
3r3663.  
The great number of bootloaders found in the network, sometimes quite entertaining, are unfortunately “sharpened” for any particular crystal. 3r3663.  
3r3663.  
The proposed material contains the procedure for using the CubeMX package, the DfuSeDemo “downloads” and the Dfu file manager firmware preparation utilities, i.e., we abstract our hot hardware from the hardware, forgive me for the macro assembler and datasheet. 3r3663.  
3r314.
3r3663.  
Cooking environment
 
3r3663.  
We need the actual CubeMX itself, the download of the DfuSeDemo + Dfu file manager, are in one package, the STM32 ST-LINK Utility, we are looking for everything on the STMicroelectronics website for free. 3r3663.  
3r3663.  
Our experimental zhleska with STM32F103C8T6 chip from Uncle Liao 3r3663.  
3r3663.  
3r330. 3r3663.  
3r3663.  
and the ST-Link programmer from there. 3r3663.  
3r3663.  
STM32 bootloader DFU mode using CubeMX. Instructions step by step, step by step 3r3663.  
3r3663.  
Well, your favorite IDE, in this particular presentation, we use KEIL, the compilation settings in other IDEs are not very different. 3r3663.  
3r3663.  
So let's go
 
3r3663.  
Launch CubeMX and choose your crystal
 
3r3663.  
3r3663.  
3r3663.  
Mark our Wishlist
 
3r3663.  
3r3365. 3r3663.  
3r3663.  
In this particular task, we activate the USB device → Device FS and, accordingly, the USB Device → DownLoad Update Firmware class, and the RCC → High Speed ​​Clock → Cristal /Ceramic Resonator is unforgettable on board. 3r3663.  
3r3663.  
Next, you need to select the bootloader mode switch, in this example, simply use the available jumper boot1. 3r3663.  
3r3663.  
3r3663.  
3r3663.  
We look at the scheme and, in accordance with it, boot1 is attached to the leg of PB? so we will use it in the GPIO_Input mode. 3r3663.  
3r3663.  
Done, activate the Clock Configuration tab and launch the configuration automat. 3r3663.  
3r3663.  
3r3391. 3r3663.  
Jump to the tab Cofiguration 3r3663.  
3r3663.  
3r3663.  
3r3663.  
Select the GPIO button 3r3663.  
3r3663.  
3r3663.  
3r3663.  
And in the field
 
3r3663.  
3r3r166. 3r3663.  
write a custom label, let it be boot1. 3r3663.  
3r3663.  
Next, set up the project
 
3r3663.  
3r3663.  
3r3663.  
Choose Project → Setting 3r3r6366.  
3r3663.  
3r3663.  
3r3663.  
Choose and fill 3r3663.  
3r3663.  
3r3145. 3r3663.  
3r3663.  
Accordingly, we choose for which IDE a Cub to us will generate a project, in our case, MDK-ARM V5. 3r3663.  
3r3663.  
The Code Generator tab in this embodiment will remain unchanged
 
3r3663.  
3r3158. 3r3663.  
3r3663.  
Well, that's all, we start the generation of the Project → Generate Code
project.  
3r3663.  
3r3167. 3r3663.  
3r3663.  
At the end, Cub will offer to immediately launch your IDE how to proceed to choose you. 3r3663.  
3r3663.  
3r3176. 3r3663.  
3r3663.  
3r3181. 3r3663.  
3r3663.  
We start compilation and assembly and loading into a crystal F? F8 3r3663.  
3r3663.  
3r3190. 3r3663.  
3r3663.  
The end result
 
3r3663.  
We switch the pins on our board to the operation mode and connect the USB cable
 
3r3663.  
3r3599. 3r3663.  
3r3663.  
3r3208. 3r3663.  
3r3663.  
Open the Windows control panel → system → device manager → USB controller. And we look at the list of devices, Windows silently rustles and installs the STM Device Driver in DFU Mode (if it was not already installed). 3r3663.  
3r3663.  
So, the driver got up and decided, run the DfuSeDemo “bootloader”
 
3r3663.  
3r3663.  
3r3663.  
We look at what the DFU Device has caught and click on the Select Target 3r3663 field.  
3r3663.  
3r3663.  
3r3663.  
Carefully we look and we marvel that the flash down to the address 0x0800C000 is closed for recording and we write down this address, we will need it 3r3663.  
3r3663.  
By the way, I tried on the STM32F407VE, there the memory is open for writing from 0x0800000? i.e. From the very beginning why, in our version is not so, it is not clear, and did not dig, it was buried somewhere, but clearly not spelled out, it is not comme il faut, because a large piece disappears without use maybe someone can tell where to dig
 
3r3663.  
So, "haircut just started" 3r3663.  
3r3663.  
We need only two source files 3r3663.  
3r3663.  
3r3663.  
3r3663.  
We open them in the IDE and we rule out 3r3663.  
3r3663.  
We take into account that CubeMX DOES NOT TOGETHER when the insert is regenerated between USER CODE BEGIN and USER CODE END there we will enter our add-ons 3r3663.  
3r3663.  
Let's start with main.c
 
3r3663.  
3r33347. /* USER CODE BEGIN PV * /
/* Private variables ---------------------------------------------- ----------- * /
typedef void (* pFunction) (void);
pFunction JumpToApplication;
uint32_t JumpAddress;
/* USER CODE END PV * /
.
.
.
/* USER CODE BEGIN 0 * /
uint32_t AddressMyApplicationBegin = 0x0800C000;
uint32_t AddressMyApplicationEnd = 0x0800FBFC;
/* USER CODE END 0 * /
.
.
.
/* USER CODE BEGIN 2 * /
/* Check if the button button is pressed * /3r3671. if (HAL_GPIO_ReadPin (boot1_GPIO_Port, boot1_Pin) == GPIO_PIN_SET)
{
/* Test if user code is programmed starting from address 0x0800C000 * /
if (((* (__ IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000) == 0x20000000)
{
/* 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 ();
}
}
MX_USB_DEVICE_Init (); /* we simply transfer this function from above * /
/* USER CODE END 2 * /
.
.
.

3r3663.  
on this with main.c all 3r3r6366.  
3r3663.  
go to usbd_conf.h and
 
3r3663.  
3r33347. #define USBD_DFU_APP_DEFAULT_ADD 0x0800000

3r3663.  
we bring to the form
 
3r3663.  
3r33347. #define USBD_DFU_APP_DEFAULT_ADD 0x080C000 //our address is written on a piece of paper

3r3663.  
go to usbd_dfu_it.c, then more 3r3663.  
3r3663.  
3r33347. .
.
.
/* USER CODE BEGIN PRIVATE_TYPES * /
extern uint32_t AddressMyApplicationBegin;
extern uint32_t AddressMyApplicationEnd;
/* USER CODE END PRIVATE_TYPES * /
.
.
.
/* USER CODE BEGIN PRIVATE_DEFINES * /
#define FLASH_ERASE_TIME (uint16_t) 50
#define FLASH_PROGRAM_TIME (uint16_t) 50
/* USER CODE END PRIVATE_DEFINES * /
.
.
.
and actually rule, or rather fill in the "dummy" working code 3r3671.
uint16_t MEM_If_Init_FS (void)
{
/* USER CODE BEGIN 0 * /
HAL_StatusTypeDef flash_ok = HAL_ERROR;
//Make the memory open
while (flash_ok! = HAL_OK) {
flash_ok = HAL_FLASH_Unlock ();
}
return (USBD_OK);
/* USER CODE END 0 * /
}
.
.
.
uint16_t MEM_If_DeInit_FS (void)
{
/* USER CODE BEGIN 1 * /
HAL_StatusTypeDef flash_ok = HAL_ERROR;
//Close the memory
flash_ok = HAL_ERROR;
while (flash_ok! = HAL_OK) {
flash_ok = HAL_FLASH_Lock ();
}
return (USBD_OK);
/* USER CODE END 1 * /
}
.
.
.
uint16_t MEM_If_Erase_FS (uint32_t Add)
{
/* USER CODE BEGIN 2 * /
uint32_t NbOfPages = 0;
uint32_t PageError = 0;
/* Variable contains Flash operation status * /
HAL_StatusTypeDef status;
FLASH_EraseInitTypeDef eraseinitstruct;
/* Get the number from the 1st sector * /
NbOfPages = ((AddressMyApplicationEnd - AddressMyApplicationBegin) /FLASH_PAGE_SIZE) + 1;
eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
eraseinitstruct.PageAddress = AddressMyApplicationBegin;
eraseinitstruct.NbPages = NbOfPages;
status = HAL_FLASHEx_Erase (& eraseinitstruct, & PageError);
if (status! = HAL_OK)
{
return (! USBD_OK);
}
return (USBD_OK);
/* USER CODE END 2 * /
}
.
.
.
uint16_t MEM_If_Write_FS (uint8_t * src, uint8_t * dest, uint32_t Len)
{
/* USER CODE BEGIN 3 * /
uint32_t i = 0;
for (i = 0; i 3r3436. {
/* Device voltage range supposed to be[2.7V to 3.6V], the operation will be
be done by by * * /
if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_WORD, (uint32_t)) , * (uint32_t *) (src + i)) == HAL_OK)
{
//Usart1_Send_String ("MEM_If_Write_FS OK!" ) (src + i)! = * (uint32_t *) (dest + i))
{
/* Flash content doesn’t match SRAM content * /
return 2; 3rr3671.}
} 3rr3671. else
{
/* Error * 3r3673. 3r3671. 3r3673. 3r3671. 3r3673. 3r3671. 3r3673. 3r3671.
* /
}
.
/* Return a valid address to avoid HardFault * /
/* USER CODE BEGIN 4 * /
uint32_t i = 0;
uint8_t * psrc = src;
for (i = 0; i < Len; i++)
{
dest[i]= * psrc ++;
}
return (uint8_t *) (dest); /* CAREFULLY, IN GENERATION PDEFAULT OTHER * /
/* USER CODE END 4 * /
}
.
.
.
uint16_t MEM_If_GetStatus_FS (uint32_t Add, uint8_t Cmd, uint8_t * buffer)
{
/* USER CODE BEGIN 5 * /
switch (Cmd)
{
case DFU_MEDIA_PROGRAM:
buffer[1]= (uint8_t) FLASH_PROGRAM_TIME;
buffer[2]= (uint8_t) (FLASH_PROGRAM_TIME 8);
buffer[3]= 0;
break;
case DFU_MEDIA_ERASE:
default:
buffer[1]= (uint8_t) FLASH_ERASE_TIME;
buffer[2]= (uint8_t) (FLASH_ERASE_TIME 8);
buffer[3]= 0;
break;
}
return (USBD_OK);
/* USER CODE END 5 * /
}

3r3663.  
Actually, that's all
 
3r3663.  
We connect the programmer, throw the jumpers into the programming mode, F? F8 and botloader are recorded 3r3663.  
3r3663.  
You can use 3r3663.  
3r3663.  
Now we will prepare our application for boot through bootloder
 
Favorite application will blink LED 3r3663.  
3r3663.  
We are preparing and debugging the application, and changing certain places in the compiler and the program body to change the program launch address and interrupt vectors 3r3663.  
3r3663.  
Namely, in KEIL → Configure → Flash Tools
 
3r3663.  
3r? 3534. 3r3663.  
3r3663.  
We change the address of the beginning of the program 3r3663.  
3r3663.  
3r? 3543. 3r3663.  
3r3663.  
We say that generated HEX file
 
3r3663.  
3r33552. 3r3663.  
3r3663.  
and changing the address of the vector table
 
3r3663.  
we assemble the program F7
 
3r3663.  
the resulting HEX is converted into a dfo file by the Dfu file manager utility
 
3r3663.  
3r? 3569. 3r3663.  
3r3663.  
specify our HEX file with the S19 or HEX button and click Generate 3r3663.  
3r3663.  
3r33578. 3r3663.  
3r3663.  
get the dfu file. 3r3663.  
3r3663.  
Actually, everything is ready. 3r3663.  
3r3663.  
Downloading to the controller
 
3r3663.  
We connect our experimental card with the botloader already loaded to USB by setting the jumpers to DFU Mode. 3r3663.  
3r3663.  
3r3599. 3r3663.  
3r3663.  
You can control the appearance of the STM Device in DFU Mode in the device list 3r3663.  
run the "boot". 3r3663.  
3r3663.  
3r3610. 3r3663.  
we point it to our dfu file
 
3r3663.  
3r31717. 3r3663.  
3r3663.  
Click Upgrade and see the download result for sure, click verification. 3r3663.  
3r3663.  
3r3663.  
3r3663.  
all right you can run 3r3663.  
3r3663.  
if the error got out, then the joint is somewhere
 
3r3663.  
3r3663.  
3r3663.  
for example 3r3663.  
3r3663.  
So, we will consider that everything is successful we switch the jumper to the application mode 3r3663.  
3r3663.  
3r3663.  
3r3663.  
and enjoy the blinking diode
 

 
Ufff. So much bukoffff. I'm tired of copying pictures :-)
 
3r3663.  
All thanks for your attention
3r3669. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r33670.
+ 0 -

Add comment