STM32 애플리케이션 노트 2606에서 이에 대해 설명하지만 간단한 코드 예제는 없습니다.STM32 F072의 소프트웨어에서 부트 로더 (DFU 모드)로 어떻게 이동합니까?
답변
이 답변은 IAR EWARM을 사용하는 STM32F072 Nucleo 보드에서 테스트되었습니다. 이 대답은 "STM32 표준 주변 장치 라이브러리"를 사용합니다.
부트 로더 모드 (DFU 모드)에서 성공적으로 작동하는지 확인하는 가장 좋은 방법은 PA_9 (USART1_TX) 라인의 USB-2-UART 변환기 (Sparkfun에서 http://sfe.io/p9873을 15 달러에 구입) 및 PA_10 (USART1_RX) (접지도 연결하는 것을 잊지 마십시오). Nucleo USART2 기본 연결 (/ dev/ttyACM0)을 사용할 수 없으므로 외부 USB-2-USART 연결을 사용할 수 없습니다. 그런 다음 USART 연결에 0x7F를 쓰는 간단한 C 프로그램을 작성하십시오. DFU 모드에 있으면 0x79로 1 바이트로 응답합니다. 우분투를 사용하기 때문에 테스트 프로그램이 컴파일되고 실행됩니다.
또한 부트 로더 모드 (일명 DFU 모드)를 테스트하는 가장 쉬운 방법은 BOOT0 라인을 + 3.3V로 점퍼하는 것입니다. 이것들은 Nucleo에서 서로 옆에 있습니다.
// Our STM32 F072 has:
// 16k SRAM in address 0x2000 0000 - 0x2000 3FFF
*((unsigned long *)0x20003FF0) = 0xDEADBEEF;
// Reset the processor
NVIC_SystemReset();
가 SystemInit() 함수의 시작 부분에 라이브러리/SYSCONFIG/system_stm32f0xx.c 몇 가지 코드를 추가합니다 :
주() 루틴 MAIN.C에 추가
// Define our function pointer
void (*SysMemBootJump)(void);
void SystemInit (void)
{
// Check if we should go into bootloader mode.
//
// Set the main stack pointer __set_MSP() to its default value. The default
// value of the main stack pointer is found by looking at the default value
// in the System Memory start address. Do this in IAR View -> Memory. I
// tried this and it showed address: 0x200014A8 which I then tried here.
// The IAR compiler complained that it was out of range. After some
// research, I found the following from "The STM32 Cortex-M0 Programming
// Manual":
// Main Stack Pointer (MSP)(reset value). On reset, the processor
// loads the MSP with the value from address 0x00000000.
//
// So I then looked at the default value at address 0x0 and it was 0x20002250
//
// Note that 0x1fffC800 is "System Memory" start address for STM32 F0xx
//
if (*((unsigned long *)0x20003FF0) == 0xDEADBEEF) {
*((unsigned long *)0x20003FF0) = 0xCAFEFEED; // Reset our trigger
__set_MSP(0x20002250);
// 0x1fffC800 is "System Memory" start address for STM32 F0xx
SysMemBootJump = (void (*)(void)) (*((uint32_t *) 0x1fffC804)); // Point the PC to the System Memory reset vector (+4)
SysMemBootJump();
while (1);
}
... // The rest of the vanilla SystemInit() function
만들기 부트 로더 모드 (일명 DFU 모드)인지 확인하는 간단한 유틸리티. 이것은 Linux에서 컴파일되어 실행됩니다. 직렬 포트를 올바르게 설치하십시오. 아래와 같이/dev/ttyUSB0이 될 것입니다.
//
// A bare-bones utility: Test if the STM32 is in DFU mode
// (aka bootloader mode, aka firmware update mode).
//
// If it is in DFU mode, you can send it 0x7F over a UART port and it
// will send 0x79 back.
//
// For details, see the STM32 DFU USART spec.
//
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h> // errno
#define DEFAULT_SERDEVICE "/dev/ttyUSB0"
//#define DEFAULT_SERDEVICE "/dev/ttyACM0"
int main(int argc, char **argv)
{
int fd, cooked_baud = B9600;
char *sername = DEFAULT_SERDEVICE;
struct termios oldsertio, newsertio;
unsigned char mydata[2] = {0};
mydata[0] = 0x7F;
mydata[1] = 0;
/* Not a controlling tty: CTRL-C shouldn't kill us. */
fd = open(sername, O_RDWR | O_NOCTTY);
if (fd < 0)
{
perror(sername);
exit(-1);
}
tcgetattr(fd, &oldsertio); /* save current modem settings */
/*
* 8 data, EVEN PARITY, 1 stop bit. Ignore modem control lines. Enable
* receive. Set appropriate baud rate. NO HARDWARE FLOW CONTROL!
*/
newsertio.c_cflag = cooked_baud | CS8 | CLOCAL | CREAD | PARENB;
/* Raw input. Ignore errors and breaks. */
newsertio.c_iflag = IGNBRK | IGNPAR;
/* Raw output. */
newsertio.c_oflag = OPOST;
/* No echo and no signals. */
newsertio.c_lflag = 0;
/* blocking read until 1 char arrives */
newsertio.c_cc[VMIN]=1;
newsertio.c_cc[VTIME]=0;
/* now clean the modem line and activate the settings for modem */
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newsertio);
// Here is where the magic happens
write(fd,&mydata[0],1);
int red = read(fd,&mydata[1],1);
if (red < 0) {
fprintf(stderr, "Error: read() failed, errno [%d], strerrer [%s]\n",
errno, strerror(errno));
}
tcsetattr(fd,TCSANOW,&oldsertio);
close(fd);
printf("Read [%d] bytes: [0x%x]\n", red, mydata[1]);
return 0;
}
내 프로젝트에서는 본질적으로 Brad와 동일하지만 SystemInit() 기능을 수정하지 않았습니다. 않는
void __attribute__((weak)) __initialize_hardware_early(void);
로
CubeMX HAL은 정의하지 않는다 - 내 경우 - 아무것도 SystemInit()를 호출 제외한;
#include <stdint.h>
#include "stm32f0xx_hal.h"
#define SYSMEM_RESET_VECTOR 0x1fffC804
#define RESET_TO_BOOTLOADER_MAGIC_CODE 0xDEADBEEF
#define BOOTLOADER_STACK_POINTER 0x20002250
uint32_t dfu_reset_to_bootloader_magic;
void __initialize_hardware_early(void)
{
if (dfu_reset_to_bootloader_magic == RESET_TO_BOOTLOADER_MAGIC_CODE) {
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *) SYSMEM_RESET_VECTOR));
dfu_reset_to_bootloader_magic = 0;
__set_MSP(BOOTLOADER_STACK_POINTER);
bootloader();
while (42);
} else {
SystemInit();
}
}
void dfu_run_bootloader()
{
dfu_reset_to_bootloader_magic = RESET_TO_BOOTLOADER_MAGIC_CODE;
NVIC_SystemReset();
}
:
그래서 당신은이 기능을 덮어 쓸 수 있습니다