如何在STM32 F072的软件中跳至引导加载程序(DFU模式)? [英] How do you jump to the bootloader (DFU mode) in software on the STM32 F072?

查看:434
本文介绍了如何在STM32 F072的软件中跳至引导加载程序(DFU模式)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

STM32应用笔记2606对此进行了讨论,但是没有简单的代码示例.

The STM32 App Note 2606 discusses this, but there is no simple code example.

推荐答案

此答案已在IAR STM32F072 Nucleo板上使用IAR EWARM进行了测试.该答案使用的是"STM32标准外围设备库",什么也没有.

This answer has been tested on the STM32F072 Nucleo board using IAR EWARM. This answer uses the "STM32 Standard Peripheral Library" and nothing else.

请注意,验证您是否成功进入引导加载程序模式(DFU模式)的最佳/最简便方法是连接USB-2-UART转换器(可从Sparkfun获得一个):

Note that the best/easiest way to verify you are successfully in bootloader mode (DFU mode) is to hookup a USB-2-UART converter (get one here from Sparkfun: http://sfe.io/p9873 for $15) on lines PA_9 (USART1_TX) and PA_10 (USART1_RX) (don't forget to connect ground as well). I was not able to use the Nucleo USART2 default connection (/dev/ttyACM0), hence the external USB-2-USART connection. Then create a simple C program to write 0x7F on the USART connection. If you are in DFU mode, it will reply with one byte: 0x79. I use Ubuntu, so my test program compiles and runs on Linux.

此外,测试引导加载程序模式(也称为DFU模式)的最简单方法是将BOOT0线跳至+ 3.3V.它们在Nucleo上紧挨着.

Also, the easiest way to test bootloader mode (aka DFU mode) is to jumper the BOOT0 line to +3.3V. These are right next to each other on the Nucleo.

添加到main.c main()例程中:

Add to main.c main() routine:

// Our STM32 F072 has:
// 16k SRAM in address 0x2000 0000 - 0x2000 3FFF
*((unsigned long *)0x20003FF0) = 0xDEADBEEF;

// Reset the processor
NVIC_SystemReset();

在SystemInit()函数的开头将一些代码添加到Libraries/sysconfig/system_stm32f0xx.c中:

Add some code to Libraries/sysconfig/system_stm32f0xx.c at the beginning of the SystemInit() function:

// 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,如下所示.

Create a simple utility to see if you are in bootloader mode (aka DFU mode). This compiles and runs on Linux. Make sure you get your serial port right. It will likely be /dev/ttyUSB0 as shown below.

//
// 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;
}

这篇关于如何在STM32 F072的软件中跳至引导加载程序(DFU模式)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆