STM32 Bootloader DFU-Modus mit CubeMX. Schritt fĂĽr Schritt Anleitung

Die Arbeit dieses Mandrigals wurde also durch das fast vollständige Fehlen von schrittweisen Anweisungen unter Verwendung der üblichen Werkzeuge von STMicroelectronics angeregt.

Die große Anzahl von Bootloadern im Netzwerk, die manchmal sehr beschäftigt sind, wird leider für einen bestimmten Kristall „geschärft“.

Das vorgeschlagene Material enthält das Verfahren zur Verwendung des CubeMX-Pakets, des DfuSeDemo-Bootloaders und des Firmware-Vorbereitungsdienstprogramms für den Dfu-Dateimanager. Das heißt, wir abstrahieren unsere Wunschliste von der Hardware und verzeihen dem Makro-Assembler und dem Datenblatt-Guru.

Die Umwelt kochen ...

Wir brauchen CubeMX selbst, den DfuSeDemo + Dfu-Dateimanager-Download, alle im selben Paket, STM32 ST-LINK Utility, finden wir alles auf der STMicroelectronics-Website kostenlos.

Unser experimenteller Stick mit dem STM32F103C8T6-Chip von Onkel Liao

Bild

und der ST-Link-Programmierer von dort.

Bild

Nun, Ihre Lieblings-IDE, in dieser speziellen Präsentation verwenden wir KEIL. Die Kompilierungseinstellungen in anderen IDEs sind nicht sehr unterschiedlich.

Also lass uns gehen ...

Starten Sie CubeMX und wählen Sie Ihren Kristall aus ...

Bild

Feiern Sie Ihre Wunschliste ...

Bild

In dieser speziellen Aufgabe aktivieren wir das USB-Gerät → Gerät FS und dementsprechend die Firmware-Klasse USB-Gerät → DownLoad-Update, und der unvergessliche RCC → Hochgeschwindigkeitsuhr → Cristal / Keramikresonator ist an Bord.

Wählen Sie als Nächstes den Bootloader-a-Modusschalter aus. In diesem Beispiel verwenden Sie einfach den vorhandenen Boot1-Jumper.

Bild

Wir schauen uns das kleine Schema an und dementsprechend ist boot1 an den Zweig von PB2 angehängt, also verwenden wir es im GPIO_Input-Modus.

Aktivieren Sie anschlieĂźend die Registerkarte Clock Configuration und starten Sie die Konfigurationsauswahlmaschine.

Bild
Zur Registerkarte "Konfiguration" springen ...

Bild

Wählen Sie die GPIO-Taste ...

Bild

Und auf dem Feld ...

Bild
Schreiben Sie ein benutzerdefiniertes Label, lassen Sie es boot1 sein.

Als nächstes richten Sie das Projekt ein ...

Bild

Wählen Sie Projekt → Einstellung ...

Bild

Auswählen und füllen ....

Bild

Dementsprechend wählen wir aus, für welches IDE Cub wir das Projekt generieren möchten, in unserem Fall MDK-ARM V5.

Die Registerkarte Codegenerator in dieser Ausführungsform bleibt unverändert ...

Bild

Nun, das ist alles, wir starten die Generierung des Projekts Projekt → Code generieren

Bild

Am Ende werden Sie von Cub aufgefordert, Ihre IDE sofort zu starten ... was Sie tun sollten.

Bild

Bild

Wir beginnen mit dem Zusammenstellen, Zusammenbauen und Laden in den Kristall ... F7, F8 ...

Bild

Das Endergebnis ...

Wir schalten die Pins auf unserer Platine in den Betriebsmodus und schlieĂźen das USB-Kabel an ...

Bild

Bild

Öffnen Sie die Systemsteuerung unter Windows → System → Geräte-Manager → USB-Controller. Schauen Sie sich die Liste der Geräte an, Windows raschelt ein wenig und installiert das STM-Gerät im DFU-Modus-Treiber (falls noch nicht geschehen).

Also stand der Fahrer auf und beschloss, den "Boot" DfuSeDemo zu starten ...

Bild

Wir schauen uns an, was wir DFU-Gerät gefangen haben und doppelklicken auf das Feld Ziel auswählen ...

Bild

Wir schauen genau hin und staunen, dass der Flash bis zur Adresse 0x0800C000 zum Schreiben geschlossen ist und wir schreiben diese Adresse, wir brauchen sie ...

Übrigens habe ich es auf STM32F407VE versucht, wo der Speicher für die Aufnahme von 0x08000000 geöffnet ist, das heißt von Anfang an ... warum es in unserer Version nicht klar ist, es gräbt nicht, es ist irgendwo begraben, aber es ist eindeutig nicht geschrieben, es gibt kein comme il faut, weil ein großes Stück besitzerlos verschwindet ... vielleicht sagt dir jemand, wo du graben sollst ...

Also, "der Haarschnitt hat gerade erst begonnen" ...

Wir brauchen nur zwei Quelldateien ...

Bild

Wir öffnen sie in IDE und korrigieren, wir fügen hinzu ...

Wir berücksichtigen, dass CubeMX beim Regenerieren des Inserts zwischen USER CODE BEGIN und USER CODE END NICHT ZUSAMMEN TUT ... dort werden wir unsere Ergänzungen eingeben ...

Beginnen wir mit main.c

/* 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 KEY Button is pressed */ 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(); /*      */ /* USER CODE END 2 */ . . . 

das ist alles mit main.c ...

gehe zu usbd_conf.h und zu

 #define USBD_DFU_APP_DEFAULT_ADD 0x0800000 

denken Sie daran ...

 #define USBD_DFU_APP_DEFAULT_ADD 0x080C000 //     … 

wir gehen zu usbd_dfu_it.c, hier mehr ....

 . . . /* 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 */ . . .   ,    «»  … uint16_t MEM_If_Init_FS(void) { /* USER CODE BEGIN 0 */ HAL_StatusTypeDef flash_ok = HAL_ERROR; //   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; //  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 of sector to erase from 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 < Len; i+=4) { /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by byte */ if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest+i), *(uint32_t*)(src+i)) == HAL_OK) { // Usart1_Send_String("MEM_If_Write_FS OK!"); /* Check the written value */ if(*(uint32_t *)(src + i) != *(uint32_t*)(dest+i)) { /* Flash content doesn't match SRAM content */ return 2; } } else { /* Error occurred while writing data in Flash memory */ return (!USBD_OK); } } return (USBD_OK); /* USER CODE END 3 */ } . . . uint8_t *MEM_If_Read_FS (uint8_t *src, uint8_t *dest, uint32_t Len) { /* 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); /* ,     */ /* 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 */ } 

Eigentlich ist das alles ...

Wir verbinden den Programmierer, werfen die Jumper in den Programmiermodus, F7, F8 und Botloader werden aufgezeichnet ...

Kann ich verwenden ...

Jetzt bereiten wir unsere Anwendung fĂĽr das Laden per Bootloder vor ...
Lieblingsanwendung blinkt LED ...

Wir bereiten die Anwendung vor und debuggen sie und ändern die einzelnen Stellen im Compiler und im Programmkörper, um die Adresse der Programmstart- und Interruptvektoren zu ändern ...

Nämlich in KEIL → Konfigurieren → Flash Tools

Bild

Ändern Sie die Adresse des Programmbeginns ...

Bild

Wir sagen, eine HEX-Datei zu generieren

Bild

und ändern Sie die Adresse der Vektortabelle ...

Sammeln des F7-Programms ...

Konvertieren Sie das empfangene HEX mit dem Dienstprogramm Dfu File Manager in eine DFO-Datei ...

Bild

Wählen Sie unsere HEX-Datei mit der Schaltfläche S19 oder HEX ... und klicken Sie auf Generieren ...

Bild

wir bekommen die dfu datei.

Eigentlich ist alles fertig.

Laden in die Steuerung ...

Wir verbinden unser Experimentierboard mit dem bereits geladenen Botloader an USB, nachdem wir die Jumper in den DFU-Modus versetzt haben.

Bild

Sie können das Erscheinungsbild des STM-Geräts im DFU-Modus in der Geräteliste steuern.
FĂĽhren Sie den "Bootloader" aus.

Bild
Sag ihr unsere Dfu-Datei ...

Bild

Wir drĂĽcken auf Upgrade und beobachten das Ergebnis des Ladens. Aus SicherheitsgrĂĽnden drĂĽcken wir auf Check.

Bild

alles ist erfolgreich ... du kannst rennen ...

Wenn der Fehler aufgetreten ist, bedeutet dies, dass irgendwo ein Pfosten ...

Bild

zum Beispiel ...

Wir gehen also davon aus, dass alles erfolgreich ist ... schalten Sie den Jumper in den Anwendungsmodus

Bild

und genieĂźen Sie die blinkende Diode ...
...
Uhhhh So viele bukoffff. MĂĽde vom Kopieren von Bildern :-)

Vielen Dank fĂĽr Ihre Aufmerksamkeit ...

Source: https://habr.com/ru/post/de432398/


All Articles