Problema de salto del gestor de arranque a la dirección de la aplicación

He escrito un cargador de arranque para mi placa, pero genera una falla grave cuando salta al código de la aplicación.

Mi error es como esta pregunta:

El cargador de arranque salta al problema de la aplicación principal usando STM32 con Keil Uvision

  • microcontrolador: stm32f103zet
  • software: Keil
  • Pines BOOT: BOOT1 y BOOT2 son 0 (modo de arranque FLASH)
  • FLASH_WRITE_ADDRESS: 0x8030000

Hice estos pasos: en el código de la aplicación :

  1. Cambié la dirección de ROM a 0x8030000.
  2. Cambié VECT_TAB_OFFSET a 0x30000
  3. Usé fromelf para crear el archivo .bin

luego escribí un código simple (parpadeo)

en el código del cargador de arranque : recibo el archivo .bin con USART y luego lo escribo en la dirección 0x8030000 de FLASH y el siguiente código:

USART_DeInit(USART1);
RCC_DeInit();

__set_CONTROL(ENABLE_PRIVILEGE_MODE);

NVIC->ICER[ 0 ] = 0xFFFFFFFF ;
NVIC->ICER[ 1 ] = 0xFFFFFFFF ;
NVIC->ICER[ 2 ] = 0xFFFFFFFF ;

NVIC->ICPR[ 0 ] = 0xFFFFFFFF ;
NVIC->ICPR[ 1 ] = 0xFFFFFFFF ;
NVIC->ICPR[ 2 ] = 0xFFFFFFFF ;

SysTick->CTRL = 0 ;
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk ;

SCB->SHCSR &= ~( SCB_SHCSR_USGFAULTENA_Msk |
                                SCB_SHCSR_BUSFAULTENA_Msk | 
                                SCB_SHCSR_MEMFAULTENA_Msk );

__disable_irq();

if( CONTROL_SPSEL_Msk & __get_CONTROL( ) )
{  /* MSP is not active */
    __set_MSP( __get_PSP( ) ) ;
    __set_CONTROL( __get_CONTROL( ) & ~CONTROL_SPSEL_Msk ) ;
}

JumpAddress=(FLASH_WRITE_ADDRESS+4);
JumpToApplication =(void(*)(void))(*((uint32_t*)JumpAddress));
__set_MSP(*(__IO uint32_t*)FLASH_WRITE_ADDRESS);
JumpToApplication();

Pero va a fallar. Así que ahora uso esta parte del código:

/* Jump to user application */
JumpAddress = *(volatile uint32_t*)(FLASH_WRITE_ADDRESS+4);
JumpToApplication = (pFunction) JumpAddress;
__set_MSP((*(volatile uint32_t*) FLASH_WRITE_ADDRESS));
now_pointer=__get_MSP();
JumpToApplication();

pero es lo mismo que antes. ¿Cual es el problema?

Este es un segundo antes de saltar al código de la aplicación:

Y este es el resultado de saltar al código de la aplicación:

okey.ahora, encuentro y resuelvo el problema: puse mi escritura en FLASH imagen de error:no con respecto a la escritura little endian en FLASH

Hasta ahora, no ha proporcionado nada para diferenciar su pregunta de la vinculada, por lo que realmente debería cerrarse como un duplicado. Tenga en cuenta que, como siempre, el consejo de mejores prácticas es establecer una bandera, hacer un reinicio y luego, al reiniciar, saltar a la aplicación antes de realizar cualquier configuración de chip. Además, su pregunta no tiene respuesta, ya que el tipo de almacenamiento de JumpAddress no se proporciona en ninguna parte, ni ha hecho nada para demostrar que la carga útil transferida se ha escrito correctamente en flash, o que se vinculó correctamente para esa dirección, para empezar.
mi pregunta es la siguiente.¿que debo hacer? tu quieres de mi, digo otra cosa??? depuré mi código una y otra vez... leí las notas de Google... observé el ejemplo de github... pero no funcionó. Y estoy esperando allí a alguien que tuvo este problema y tal vez ahora pueda ayudarme. y a punto de dar me gusta a la pregunta que dijiste: no tiene respuesta, así que hago la pregunta de nuevo. chris stratton
Debe escribir un controlador de fallas permanente adecuado que lo ayude a diagnosticar el problema. Mire los registros de fallas para ver qué tipo de falla ocurrió y verifique que realmente sabe qué instrucción de ensamblaje la causó. Use puntos de interrupción antes de la instrucción infractora y luego siga un solo paso a través de su código. Esto no es magia, es solo depuración. No espere que las respuestas provengan de Internet o mirando el código.
¿Cómo obtuviste una dirección extraña en la PC? eso se quita al entrar. Idealmente, desea usar bx o blx manualmente con una pequeña cantidad de ensamblaje; de ​​lo contrario, debe verificar que el desensamblaje esté usando las instrucciones correctas con la dirección correcta.
¿Qué has hecho para depurar esto aparte de usar este depurador que claramente no está ayudando? no mostraste el salto relevante al código de la aplicación.
¿Qué sucede cuando pones un simple salto a uno mismo (bucle infinito) en la dirección de destino?
¿Qué significa el primer puñado de palabras si su aplicación de destino se parece a dónde está el volcado de eso?
Mire el valor que tiene en su variable JumpAddress. Es de esperar que esté en algún lugar de su rango 0x0803xxxx, pero tiene 0x03084501. Para mí, parece que está haciendo una confusión de little-endian/big-endian con los datos que ingresan a través del UART que se escriben en flash. Si mezcla los bytes, obtendrá 0x08030145, que tendría mucho más sentido como la dirección de inicio del código de su aplicación.
Consulte la barra de herramientas de Keil, Periféricos -> Periféricos centrales -> Informe de fallas para verificar qué tipo de falla grave está recibiendo.
Yo checo esto. La bandera IBUSSERR y STKERR cambian a 1 @Jeroen3@Elliot Alderson

Respuestas (3)

Lo más probable es que utilice el código de inicio estándar del STM en la aplicación de usuario. Establece VTOR al comienzo de la memoria FLASH. Elimina esta línea y debería funcionar.

Encuentro mi error y lo soluciono. Ahora mi cargador de arranque funciona correctamente.

pero mi problema:

1- i contraté, cambie la línea de dirección del vector, después de principal en el archivo de la aplicación.

2- comenté estas líneas en el archivo del gestor de arranque:

__disable_irq();
__set_MSP((*(volatile uint32_t*) FLASH_WRITE_ADDRESS));

Aparte de eso, tuve un error al escribir en flash (no con respecto al pequeño indio)

y ahora mi código funciona correctamente

gracias de todos me ayudan a resolver este problema.

Probablemente esa línea estaba invalidando su referencia a JumpAddress; nunca respondió la pregunta sobre su clase de almacenamiento. Lo que está haciendo ahora solo funciona porque el cargador de arranque y el programa principal tienen el mismo diseño de RAM, si necesita cambiar la forma en que el programa principal usa la RAM, puede romperse.
sí. Tal vez no funcione si el cargador de arranque y la aplicación principal no tienen la misma RAM. pero recuerda que es mi primera aplicación de cargador de arranque. Puedo mejorarlo en el futuro =) @ Chris Stratton

Como la corteza m0+ no tiene algunos de los sofisticados intermedios de 32 bits o incluso de 16 bits y como compilará hasta un límite de 1K, solo tiene que apuntar a la nueva tabla de vectores con un desplazamiento de 8 bits a la izquierda.

  if ( firm1 > firm2) __asm("movs r0, #0x40");       // firmware at 0x4000
  else __asm("movs r0, #0xa0");                      // for firmware at 0xa000
 
   __asm("lsls r0, r0, #8");  
   __asm("ldr  r1, [r0]");  
   __asm("msr  msp, r1");              // Set new MSP 
   __asm("msr  psp, r1");              // PSP based on SP 
   __asm("ldr  r1, [r0,#0x4]");  
   __asm("mov  pc, r1");               // Jump by changing PC 
Ese no es un análisis del todo correcto, ya que si el ancho de las instrucciones fuera el problema, habría un error durante la compilación. En realidad, los compiladores funcionan bien sintetizando constantes más grandes e indirectamente lo que el hardware no puede hacer directamente. Sin embargo, lo que puede haber logrado es evitar cierta dependencia de la pila que podría causar que el código del OP falle después de haber cambiado el MSP, pero nunca obtuvimos detalles de implementación sobre en qué se compila el código del OP.