STM32L011 saltar al cargador de arranque desde el código de usuario

0

Estoy intentando hacerlo para que mi STM32L011 pueda pasar del código de usuario al cargador de arranque ST que permite reprogramar el flash en USART2. Esta es hipotéticamente la misma pregunta que STM32F091 Saltar al cargador de arranque desde la aplicación , pero no estoy teniendo suerte con las correcciones de deshabilitación periférica de esa pregunta. ST rehizo sus foros y rompió todos los enlaces antiguos a hilos, por lo que me está costando muchísimo encontrar pistas sobre otros posibles problemas y estoy bastante perplejo en cuanto a dónde buscar a continuación.

Mi función de salto es la siguiente (modificada de la pregunta anterior para mi aplicación y utilizando las bibliotecas ST LL). El código de mi aplicación utiliza el LPUART en PA2 / PA3, que USART2 debería utilizar para el cargador de arranque. Se recibe un comando en el LPUART en el código de la aplicación de usuario, que llama a la función de salto. El código de la aplicación reconoce el comando correctamente de acuerdo con mi protocolo serie, pero luego el cargador de arranque USART no responde a ninguna utilidad intermitente. Envían el byte inicial 0x7F por AN2606 pero el cargador de arranque no envía el ACK de vuelta.

#define STM32L01_SYSTEM_MEMORY  0x1FF00000

void jump_to_bootloader()
{
    // Disable global interrupts
    __disable_irq();

    // Disable interrupt requests from peripherals
    NVIC_DisableIRQ(SysTick_IRQn);
    NVIC_DisableIRQ(LPUART1_IRQn);
    NVIC_DisableIRQ(EXTI0_1_IRQn);
    NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
    NVIC_DisableIRQ(I2C1_IRQn);

    typedef void (*pFunction)(void);
    volatile uint32_t addr = STM32L01_SYSTEM_MEMORY;
    uint32_t jumpaddr = *(__IO uint32_t*) (STM32L01_SYSTEM_MEMORY + 4);
    pFunction jump_to_application;

    // Application-specific shutdown of HSE and switch to MSI
    clock_HSE_to_MSI();

    // Reset ALL peripherals
    LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_ALL);
    LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_ALL);
    LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ALL);
    LL_mDelay(5);

    LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_ALL);
    LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_ALL);
    LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ALL);
    LL_mDelay(5);

    // Fully reset RCC to power-up state
    LL_RCC_DeInit();

    // Zero out SysTick
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;


    // Remap memory to system flash
    SYSCFG->CFGR1 = 0x01;

    jump_to_application = (pFunction)jumpaddr;

    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) addr);


    jump_to_application();
}

He descartado estos problemas:

  1. Los pines de control en mi transceptor RS322 MAX3221 (NEN, NFORCEOFF, FORCEON) están en los estados habilitados apropiados, por lo que si USART2 está hablando, debería ver algo en mi analizador lógico que está conectado al lado RS232. Desafortunadamente, la necesidad de controlar los pines GPIO en el momento del arranque para configurar estos pines de control significa que no puedo hacer la prueba "llamar a mi función de salto al inicio de la prueba principal ()".
  2. La función jump_to_bootloader () se ejecuta completamente (no se bloquea en el interruptor de reloj, etc.). Veo que uno de los pines de control MAX3221 se eleva por alrededor de 160us antes de volver a estar bajo, lo que he confirmado que sucede después de cualquier punto en la función que podría cambiarlo de esa manera. Estoy operando bajo el supuesto de que esto ocurre como parte del periférico GPIO que se está inicializando nuevamente.
  3. He intentado varias combinaciones de incluir las llamadas de instrucciones de barrera de memoria incluidas en la pregunta mencionada anteriormente sin ningún efecto. No he encontrado ninguna referencia a los que están incluidos en ningún otro código similar en línea.
  4. Estoy restableciendo todos los periféricos para garantizar que no tenga el mismo problema que la pregunta anterior. En teoría, esto debería anular la necesidad de intentar llamar a la función de salto al inicio de main (). También estoy deshabilitando específicamente las solicitudes de interrupción utilizadas en mi aplicación para estar seguros.
  5. Nunca veo que el pin de reinicio del chip se apague, así que no sospecho nada con el pin BOOT0 en este momento. El pin se mantiene bajo con una resistencia desplegable, por lo que si se produce un reinicio, BOOT0 causará que el chip vuelva a arrancar el código de usuario en flash. Los bytes de la opción de chip se establecen de la siguiente manera:

Teoríasdetrabajo:

  1. Algopodríaestaryendomalcondondeestoysaltando.Porloquesé,tengoladireccióncorrectadeAN2606.Tengoproblemasparaconfirmarestoalmirarlosregistrosconundepurador.Despuésdepasartodoelcaminoatravésdejump_to_bootloader(),elcódigoparececolgarse,almenosdeacuerdoconeldepurador...Noentiendocompletamentesitodavíapuedoconfiareneldepuradordespuésdesaltardemicódigodeusuario.LosregistrosSPyMSPmuestrandireccionesSRAM(rango0x20000000)ylaPCestáenflash(inicio0x80000000).

Antesde__set_MSP():

Despuésdepasaralfinaldelafuncióndesalto(losbotonesdepasodeldepuradoryanoestánhabilitados):

Siluegohagoclicensuspenderejecucióneneldepurador,medevuelveaunpuntodeinterrupcióngeneradoporEclipsealiniciodemain().Noentiendocómopodríaseresteelcaso,yaqueelcódigodemiaplicaciónyanofuncionacorrectamente,conosineldepuradorpresente.

  • Algo está causando un restablecimiento que no veo en el pin de hardware por alguna razón, lo que está causando un reinicio en la memoria flash del usuario. Esto se siente como una pista falsa, pero desconfío debido a la forma en que el depurador me devolvió al inicio de main ().
  • pregunta Joe Baker

    0 respuestas

    Lea otras preguntas en las etiquetas