STM32-Bootloader-DFU-Modus mit CubeMX. Anleitung Schritt für Schritt, Schritt für Schritt

Published on December 07, 2018

STM32-Bootloader-DFU-Modus mit CubeMX. Anleitung Schritt für Schritt, Schritt für Schritt

Ausschlaggebend für den Aufsatz dieses Mandalas war das fast vollständige Fehlen einer Schritt-für-Schritt-Anleitung mit den von STMicroelectronics gebräuchlichen Werkzeugen.

Die große Anzahl von Bootloadern im Netzwerk, die manchmal recht unterhaltsam sind, ist leider für einen bestimmten Kristall "geschärft".

Das vorgeschlagene Material enthält die Prozedur für die Verwendung des CubeMX-Pakets, der DfuSeDemo- "Downloads" und der Dfu-Dateimanager-Firmware-Vorbereitungsprogramme, d.h.

Wir

bereiten die Umgebung vor ... Wir brauchen den eigentlichen CubeMX selbst, den DfuSeDemo + Dfu-Dateimanager-Download, sind im selben Paket, STM32 ST-LINK Utility, wir suchen alles auf der STMicroelectronics-Website kostenlos.

Unser experimenteller STZ32F103C8T6-Chip von Onkel Liao

Bild

und ST-Link-Programmierer aus der gleichen Region.

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 ...

Starte CubeMX und wähle deinen Kristall ... Markiere

Bild

deinen Wunschzettel ...

Bild

Aktiviere in dieser bestimmten Aufgabe das USB-Gerät → Geräte-FS und dementsprechend die Firmware-Klasse USB-Gerät → Firmware-Download, und der RCC → Hochgeschwindigkeits-Taktgeber → Kristall / Keramik-Resonator ist unvergesslich Bordgebühren.

Als nächstes müssen Sie den Bootloader-Modusschalter auswählen. In diesem Beispiel verwenden Sie einfach den verfügbaren Jumper boot1.

Bild

Wir sehen uns das Schema an und dementsprechend ist boot1 mit dem Abschnitt von PB2 verbunden, sodass wir es im GPIO_Input-Modus verwenden werden.

Fertig, aktivieren Sie die Registerkarte Clock Configuration und starten Sie den Konfigurationsautomaten.

Bild
Wechseln Sie zur Registerkarte Konfiguration ...

Bild

Wählen Sie die GPIO-Schaltfläche ...

Bild

und geben Sie im Feld ...

Bild
ein benutzerdefiniertes Etikett ein, und lassen Sie es boot1 sein.

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

Bild

Wählen Sie Projekt → Einstellung ...

Bild

Auswählen und ausfüllen ....

Bild

Dementsprechend wählen wir, für welche IDE ein Cub für uns ein Projekt generiert, in unserem Fall MDK-ARM V5.

Lesezeichen für den Codegenerator in dieser Ausführungsform bleiben unverändert ...

Bild

Nun, das ist alles, wir beginnen mit der Generierung des Projekts → Code generieren

Bild

Am Ende bietet der Cub an, Ihre IDE sofort zu starten ... wie Sie vorgehen müssen, um Sie auszuwählen.

Bild

Bild

Wir starten die Zusammenstellung und Montage 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 in Windows → System → Gerätemanager → USB-Controller. Und wir schauen uns die Geräteliste an, Windows raschelt leise und installiert den Treiber STM Device im DFU-Modus (falls dies noch nicht geschehen ist).

Also stand der Fahrer auf und entschied, das "Booten" von DfuSeDemo zu starten ...

Bild

Wir schauen uns an, was wir für ein DFU-Gerät haben und klicken auf das Feld Ziel auswählen

Bild

Wir beobachten und staunen, dass der Flash-Down zur Adresse 0x0800C000 für die Aufnahme geschlossen ist und schreiben diese Adresse, wir werden sie brauchen ...

Übrigens, ich habe STM32F407VE ausprobiert, da ist der Speicher für die Aufnahme von 0x08000000 offen, d. H. Von Anfang an ... warum in unserer Version nicht so, unklar und nicht ausgegraben, irgendwo vergraben, aber eindeutig nicht ausgeschrieben, nicht comme il faut, denn ein großes Stück verschwindet ohne eines ... kann mir jemand sagen, wo ich graben soll ...

Also "der Haarschnitt wird gerade angefangen" ...

Wir brauchen nur zwei Feilen Quellcode ...

Bild

öffnen sie in der IDE und pravim- Ergänzung ...

zu berücksichtigen , dass CubeMX n NICHT Toga Regeneration und fügen Sie zwischen USER CODE BEGIN und USER CODE END ... und es wird unsere Ergänzungen beschriften ...

Zunächst 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 */
.
.
.

dazu mit main.c alle ...

gehe zu usbd_conf.h und in

#define USBD_DFU_APP_DEFAULT_ADD     0x0800000

wir erinnern uns ...

#define USBD_DFU_APP_DEFAULT_ADD     0x080C000 // наш адрес записанный на бумажке…

gehe zu usbd_dfu_it.c, dann 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, springen die Jumper in den Programmiermodus, F7, F8 und Botloader werden aufgezeichnet ...

Sie können verwenden ...

Jetzt bereiten wir unsere Anwendung zum Booten über den Bootloder vor ...
Lieblingsanwendung blinkt LED ...

Wir bereiten und debuggen die Anwendung und ändern sie im Compiler und im Programmkörper getrennten Orten auf Adressprogrammstart ändern und Interrupt - Vektoren ...

nämlich in KEIL → konfigurieren → Flash - Werkzeuge

Bild

die Adresse des Beginns des Programms ändern ...

Bild

Sprechen Sie die HEX - Datei zu erzeugen ,

Bild

und ändern Sie die Adresse der Vektortabelle ...

mit Biran Programm F7 ...

was dfo Transformation HEX - Datei - Dienstprogramm Dfu Datei - Manager ...

Bild

Geben Sie unsere HEX-Datei mit der S19- oder HEX-Taste an ... und klicken Sie auf "Generieren".

Bild

Wir erhalten die DFU-Datei.

Eigentlich ist alles fertig.

Herunterladen in den Controller ... Wir

verbinden unsere Testkarte mit dem bereits auf USB geladenen Botloader, nachdem zuvor die Jumper in den DFU-Modus versetzt wurden.

Bild

Sie können das Erscheinungsbild des STM-Geräts im DFU-Modus in der Geräteliste steuern ...
Starten Sie den "Uploader".

Bild
Wir verweisen auf unsere DFU-Datei.

Bild

Klicken Sie auf Upgrade und sehen Sie sich das Download-Ergebnis an. Um sicherzugehen, klicken Sie auf Verifizierung.

Bild

alles ist gut ... du kannst rennen ...

wenn der Fehler rauskommt, dann gibt es einen Fehler ...

Bild

zum Beispiel ...

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

Bild

und genießen die blinkende Diode ...
...
Ufff. Soviel bukoffff. Ich bin es leid Bilder zu kopieren :-)

Das wars , danke für deine Aufmerksamkeit ...