Un artículo para obtener el puerto serie virtual IAP

    在上一篇博客中我提到了STM32F407+虚拟串口在线升级的基本原理,这一篇我讲一下关于一些,在虚拟串口在线升级的代码和注意的一些细节。
    在线升级原理不清楚的请移步参考上一篇[我用一张图了解虚拟串口IAP](https://blog.csdn.net/cs111211/article/details/105142049)

1. Explicación del código de actualización

  1)拷贝app代码到flash。
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite) 
{ 
  FLASH_Status status = FLASH_COMPLETE;
 u32 addrx=0;
 u32 endaddr=0; 
  if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return; //非法地址
 FLASH_Unlock();         //解锁
  FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间禁止数据缓存。
   
 addrx=WriteAddr;    //写入起始地址
 endaddr=WriteAddr+NumToWrite*4; //写入结束地址
 if(addrx<0X1FFF0000)   //只有主存储区才执行擦除操作 !
  while(addrx<endaddr)  //对非0xFF的地方先擦除
   if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//擦除非0XFFFFFFFF地方
   {   
    status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间
    if(status!=FLASH_COMPLETE)break; //发生错误了
   }else addrx+=4;
  } 
 }
 if(status==FLASH_COMPLETE)
 {
  while(WriteAddr<endaddr)//写数据
  {
   if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据
   { 
    break; //写数据异常
   }
   WriteAddr+=4;
   pBuffer++;
  } 
 }
  FLASH_DataCacheCmd(ENABLE); //FLASH擦除结束,开启数据缓存
   FLASH_Lock();//上锁
} 

u32 iapbuf[512];  //缓冲
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
{
 u32 t;
 u16 i=0;
 u32 temp;
 u32 fwaddr=appxaddr;//写入当前的地址
 u8 *dfu=appbuf;
 for(t=0;t<appsize;t+=4)
 {         
  temp=(u32)dfu[3]<<24;   
  temp|=(u32)dfu[2]<<16;    
  temp|=(u32)dfu[1]<<8;
  temp|=(u32)dfu[0];   
  dfu+=4;//偏移4个地址
  iapbuf[i++]=temp;     
  if(i==512)
  {
   i=0; 
   STMFLASH_Write(fwaddr,iapbuf,512);
   fwaddr+=2048;//偏移2048  512*4=2048
  }
 } 
 if(i)STMFLASH_Write(fwaddr,iapbuf,i);// 
}

2) Cómo usar el código La
parte anterior del código es un método para escribir la aplicación en el área especificada de FLASH. Debe agregar la biblioteca flash al proyecto en el proyecto.
Eso es stm32f4xx_flash.c.
Estas funciones se usan para escribir aplicaciones, necesitamos llamar a la interfaz que está vacía iap_write_appbin (u32 appxaddr, u8 * appbuf, u32 appsize). Hay tres parámetros de entrada:

  1. appxaddr: es la dirección especificada escrita en flash. Para direcciones específicas que se pueden escribir, consulte mi dirección de escritura inicial. Escribí la dirección superior de la pila de aplicaciones. #define FLASH_APP1_ADDR 0x08010000 esta dirección. Debido a que el programa de arranque no es demasiado grande, reservamos 64k de memoria para el programa de arranque, que es 0x10000. La dirección de inicio del flash es 0x08000000, por lo que la dirección de inicio de la primera aplicación es 0x080000000 + 0x10000 = 0x08010000. Por supuesto, puedes descargar múltiples aplicaciones para flashear. (Mientras la memoria FLASH sea suficiente) Puede verificar la dirección del sector flash en la hoja de datos del chip donde puede almacenar la aplicación.
  2. appbuf: es el búfer del programa de la aplicación, que es el código de la aplicación ()
  3. tamaño de la aplicación: el tamaño del programa de la aplicación (bytes)

2. Código de salto y puntos de atención

Primero ve al código y ve al programa de aplicación

void iap_load_app(u32 appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法
{
 __disable_irq();//关闭所有中断
 RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_OTG_FS, ENABLE); 
 RCC_AHB2PeriphResetCmd(RCC_AHB2Periph_OTG_FS, DISABLE); //复位USB OTG
 TIM_Cmd(TIM3,DISABLE);//定时器失能
 jump2app=(iapfun)*(vu32*)(appxaddr+4);  //代码区第二个字是程序开始地址(复位地址) 
 MSR_MSP(*(vu32*)appxaddr);     //初始化app堆栈指针(第一个字用于存放栈顶地址)
   jump2app();         //转跳到app
}
}   

El código anterior es el código que salta a la aplicación. Aquí hay un punto.
1) Apague todas las interrupciones
Antes de saltar a la aplicación , apague todas las interrupciones que se hayan activado. Debido a que la actualización solo se enciende una vez, si la interrupción no se desactiva, nada cambiará en el registro de interrupciones. Después de saltar al programa de la aplicación, la interrupción sigue ahí, pero la función de interrupción se ha ido. El programa no sabe de dónde vino la interrupción, por lo que hará que el programa se congele. Entonces use __disable_irq (); // Apague todas las interrupciones
2) Los periféricos deshabilitados
que se han encendido son similares al punto anterior, porque el temporizador y el puerto serie virtual usb se usan en mi programa de cargador de arranque y el programa de la aplicación También se utilizan temporizadores y puertos serie virtuales. Entonces, si puede usar estos periféricos en la aplicación normalmente, debe deshabilitarlos antes de saltar, y la forma de deshabilitar los periféricos es deshabilitar su reloj.
RCC_AHB2PeriphResetCmd (RCC_AHB2Periph_OTG_FS, ENABLE);
RCC_AHB2PeriphResetCmd (RCC_AHB2Periph_OTG_FS, DISABLE); // Estas dos oraciones se restablecen USB OTG
TIM_Cmd (TIM3).
3) Implemente
jump2app = (iapfun) (vu32 ) (appxaddr + 4); Esta oración corresponde al segundo elemento en la tabla de vectores de interrupción de la aplicación, y la dirección de reinicio se obliga a convertirse en un puntero de función
MSR_MSP ( (vu32 ) appxaddr); // Inicializar el puntero de la pila de la aplicación (la primera palabra se usa para almacenar la dirección superior de la pila)
es establecer el puntero de la pila de la función principal.
La última oración jump2app (); // Salta a la función de llamada a la aplicación, ve a la dirección de reinicio de la aplicación para realizar la operación de reinicio

3. Cómo generar una aplicación

1) Establezca la dirección superior de la pila. El
programa APP agrega esta oración
SCB-> VTOR = 0x8000000 | 0X10000 después de la definición de la variable de función principal ;
esta oración significa que la dirección superior de la pila de aplicaciones es 0x08010000. Del mismo modo, se pueden configurar otras direcciones.
2) Establezca agregar
en la opción de destino en destino para que las opciones se editen de acuerdo con la siguiente figura. La dirección después del primer cuadro después de IROM1 se cambia a 0x08010000. Esta dirección es la dirección de inicio de la aplicación, y el segundo cuadro se cambia a 0xf0000. Es el tamaño del programa de aplicación. El flash que uso aquí es de 1 m, por lo que tamaño = 1M-64k = 0xf0000. El contenido de estos dos cuadros debe ser un múltiplo entero de 0x400.
Inserte la descripción de la imagen aquí
4) Después de generar el archivo bin
Después de configurar la dirección, necesitamos algo para convertir el programa en un archivo bin. Esta función se puede implementar en keilv5. Primero encuentre la ruta de fromelf.exe y luego encuentre el nombre del archivo en su salida. Mi proyecto aquí es USART, y luego se generará un archivo con el sufijo .axf después de la compilación.
Inserte la descripción de la imagen aquí
Luego
Inserte la descripción de la imagen aquí
marque la opción Ejecutar # 1 en la opción de usuario y complete una ruta en el siguiente formato en el siguiente cuadro E: \ MDK5 \ ARM \ ARMCC \ bin \ fromelf.exe --bin -o ... \ OBJ \ USART.bin ... \ OBJ \ USART.AXF está
delante de la ruta fromelf.exe \ --bin -o ... \ OBJ \ USART.bin ... \ OBJ \ USART.AXF
Luego haga clic en Aceptar, haga clic en compilar y aparecerá el siguiente mensaje en el área de salida que indica que el archivo bin se generó correctamente. Puede encontrar el archivo USART.bin en la carpeta OBJ.
Inserte la descripción de la imagen aquí

4. Algunos puntos de atención del programa de aplicación.

1. Para activar la interrupción en la aplicación, debe activar la interrupción e inicializar los periféricos utilizados para habilitar el reloj periférico correspondiente al comienzo de mian.
2. La ruta en el usuario debe ingresarse correctamente o se informará un error. El mío está en la ruta de E: \ MDK5 \ ARM \ ARMCC \ bin \ fromelf.exe, esto será diferente según la ubicación de su instalación de MDK.
3. Asegúrese de agregar SCB-> VTOR = 0x8000000 | 0X10000; en el programa. De lo contrario, el código no se ejecutará después de la actualización.

3 artículos originales publicados · Me gusta2 · Visitas 112

Supongo que te gusta

Origin blog.csdn.net/cs111211/article/details/105533524
Recomendado
Clasificación