KBOOT - booting from ROM causes the program to hang after a single loop run - KL43 board

cancel
Showing results for 
Search instead for 
Did you mean: 

KBOOT - booting from ROM causes the program to hang after a single loop run - KL43 board

796 Views
piotrcerba
Contributor III

After programming the board with KBOOT 1.2.0 default file from \apps\binaries\FRDM_KL43Z4.bin with the help of blhost, I changed the Flash configuration FOPT register so that device starts from ROM:

/* Flash Configuration */

    .section .FlashConfig, "a"

    .long 0xFFFFFFFF

    .long 0xFFFFFFFF

    .long 0xFFFFFFFF

    .long 0xFFFFFEFE /*now starting from ROM*/

Now I have the following problems (when I debug the app in KDS everything works fine):

1. After exiting debug mode and simply reconnecting the USB cable, the device waits around 3-4 seconds before it starts

2. When it starts, after two-three main while loop runs - it stops (I see it because I have put a counter that is shown on the LCD)

3. When I connect the USB to the KL43 USB port (not OpenSDA port), only part of my LCD screen is working, so apparently it does not even go through the main loop once

I am confused now, because if I want to upload new program using blhost.exe then I need to set FOPT to boot from ROM. And after doing it the program does not run correctly.

What am I doing wrong?

EDIT: I realized that running

blhost -p COM13 -- write-memory 0 FRDM_KL43Z4.bin

I placed the bootloader in Flash memory (adress 0). And according to Chapter 4.5 System memory map:

Program flash and read-only data

(Includes exception vectors in first 196 bytes)

I may have overwritten the vectors.

Is that wrong?

Labels (2)
0 Kudos
7 Replies

273 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Piotr Cerba:

I guess you are confused. There is no need to load KBOOT or any bootloader to the KL43. The KL43 devices come from factory with a dedicated ROM memory which is already programmed with the bootloader itself, you just need to connect with one of the available interfaces (UART, USB HID, SPI, I2C) using any of the PC Host tools (KinetisUpdater or blhost).

The binary you mention at the beginning of your post is just an example project to demonstrate that from your application you can call the flash driver APIs stored in the dedicated ROM memory. You can connect the OpenSDA virtual serial interface at a 19200 baud and see what the example project does. Apart from that there is no need to load such binary, so you can ignore it.

Now regarding your questions:

1) By default when booting from ROM the bootloader will wait ~5 seconds before jumping to the application. You can change this time by writing to BCA configuration space in your application project. See the next document about that:

:smileyalert: NOTE: Do not pay attention to the linker file modifications or any application/vector offsets. Since the KL43 has the ROM bootloader integrated, there is no need to accommodate space for a bootloader at the start of flash memory.

Adapting KDS project for KBOOT flash resident bootloader

2) Please search in the KL43 Reference Manual the chapter about Bootloader Errata. Some registers are written during ROM bootloader execution and then not returned to default values. Check that such register modifications do not interfere with your application's code.

3) Same as (2).

If after checking this you are still unsure at what the problem is, please share your project so I can give it a check from my side.

Regards!

Jorge Gonzalez

0 Kudos

273 Views
piotrcerba
Contributor III

Thank you for the answer Jorge Gonzalez

Regarding the "NOTE": According to blhost User Guide, the write-memory command "Writes a provided buffer to a specified range of bytes in memory. Can write to all accessible memory, including flash, RAM, and peripheral registers."

If I wrote

blhost -p COM13 -- write-memory 0 FRDM_KL43Z4.bin

then was it written to Flash or ROM? The .pdf does not mention ROM.

Some other questions that popped to my mind:

1. If \apps\binaries\FRDM_KL43Z4.bin is not a bootloader as you say, then is KBOOT built-in every board? If not - how do I implement it then?

I thought that I currently have OpenSDA bootloader and by programming the board with \apps\binaries\FRDM_KL43Z4.bin I will have KBOOT.

Why do I want KBOOT? I just want a bootloader that allows for easy update of the app and at the same time it does not allow debugging (like OpenSDA) thereby securing the device completely.

-----

EDIT: One observation I made:

If I reconnect the board and during those 5 seconds of ROM bootloader operation - I reset the board by means of blhost

blhost -p COM13 -- reset

Then the program works correctly (the loop is incremented up to 200 on my LCD).

If I don't reset the board in blhost, then then board runs through main only a couple of times (undefined behaviour since sometimes it is 3 times, sometimes 7)

0 Kudos

273 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Piotr,

- In the command you showed above, the address is 0, which in the system memory map corresponds to Flash memory, so the binary is loaded to Flash memory.

KBOOT and OpenSDA are two different concepts not strictly related to each other.

- KBOOT is a bootloader available in 3 versions: Flash-resident bootloader, Flashloader and ROM bootloader.

See the table in the product page: Kinetis Bootloader|Freescale

The KL43 has a ROM memory programmed in factory with the bootloader. If you build a custom board with KL43, then such board will already have the bootloader available.

Notice that KBOOT does not provide any debug functionality.

- OpenSDA is an on-board interface to program and/or debug the target MCU in Freedom/Tower boards. OpenSDA firmware is actually programmed in a separate MCU, a Kinetis K20. When building a custom board and if you wish to be able to debug the KL43, then basically you have 2 options:

1) Solder a SWD header (like J11 in FRDM-KL43Z) and use an external tool (e.g. Segger J-Link or P&E Micro Universal Multilink)

2) Replicate the OpenSDA interface (with a K20) in your custom board.

To secure the device you only need to write to the FSEC byte in Flash space. In a KDS project you have the Flash configuration options in the file startup_<device>.S.

About the issue with your application, then as mentioned I guess it is related with the registers modified by the ROM bootloader. When you send the "Reset" command the KL43 is reset but it boots directly from the application and not from the bootloader.

I hope this clarifies your doubts.

Regards!

Jorge Gonzalez

0 Kudos

273 Views
piotrcerba
Contributor III

I managed to fix my code, so that after re-plugging the USB cable, the board succesfully runs without stopping after first/second iteration :smileyhappy:

The thing that fixed that was:

__disable_irq();

placed before while(1) loop.

1. Is it a proper way of fixing the problem? I am aware that I omit the HardFault handler just by disabling interrupts. What if my code used some IRQs?

2. Now, after running blhost command

-- get-property 1

the board does not stop and I am glad about it. However, it still does not respond to the ping from blhost:

Error: Initial ping failure: No response received for ping command.

What can I do if I want to allow the end user to update the application on the board without putting the restriction of running blhost within 5 seconds from powering the board up?

3. If I run

-- get-property 1

within that 5 second period after powering up, the device succesfully responds, however, afterwards it does not start the application.

When I am not pinging the board - then the application starts correctly. Why is that happening?

0 Kudos

273 Views
piotrcerba
Contributor III

Hello again. I managed to go a little further with my understanding of those bootloader problems.

However, I still encounter the following difficulties:

1. blhost can only download .bin when the device still operates on the ROM bootloader (so within 5 seconds after powering the board up). I know that this can be done correctly since in the example .bin file available in FSL_Bootloader (FRDM_KL43Z.bin) - the board responds to blhost all the time (without stopping the operation of the software).

After looking in "Bootloader errata" chapter I see that:

Affected PORT clock gates: PORTA, PORTB, PORTC, PORTD and PORTE

(SIM_SCGC5_PORTA, SIM_SCGC5_PORTB, SIM_SCGC5_PORTC,

SIM_SCGC5_PORTD and SIM_SCGC5_PORTE are enabled)

• Affected pin mux: LPUART0(PTA1, PTA2), I2C0(PTB0,PTB1),

SPI0(PTC4,PTC5,PTC6,PTC7)

• Affected peripheral registers:

     •     UART and UART clock source (SIM_SOPT2_UART0src=3)

     •      SPI

     •      I2C

I don't use UART and I2C, so the problem must lay somewhere in my SIM_SCGC5 init, hardware_init from SDK or SPI init. I was not aware that in my app I might have been relying on some default initializations.

Below is the code of those three functions, are there any "0s by default" missing?

void SIMMod_Init(void)

{

  SIM_SOPT1CFG = 0; //not using USB

  SIM_SOPT1 = 0;

  SIM_SOPT4 = 0;

  SIM_SOPT5 = 0;

  SIM_SOPT7 = 0;

  SIM_SCGC4 = 0xf0000030;

  SIM_SCGC5 = 0x00003F82; //clock to PORTA-PORTE

  SIM_SCGC7 = 0; //not using DMA

  SIM_CLKDIV1 = 0x00010000; //DIV1 1, DIV4 2

}

void SPI_init(void)

{

  SIM_SCGC4 |= 0x00800000; //clock for SPI1 (bus clock 24MHz)

  PORTC_GPCLR = 0x00070100;

  GPIOC_PDDR = 0x00000007; //PC0..2 as output

  PORTB_PCR18 = 0x00000140;

  GPIOB_PDDR = 0x00040000; //PB18 as output

  PORTD_GPCLR = 0x00600200; //PC6..7 as Alt2 (SPI0_SCK i MOSI)

  SPI1_C1 = 0x50;    //enable spi, master, clock polarity and phase

  SPI1_C2 = 0; //8bit mode

  SPI1_BR = 0x32; //baudrate prescaler is 6 (f=4MHz)

  GPIOB_PSOR = 0x00040000;

}

void hardware_init(void)

{

  /* enable clock for PORTs */

  CLOCK_SYS_EnablePortClock(PORTA_IDX);

  CLOCK_SYS_EnablePortClock(PORTC_IDX);

  CLOCK_SYS_EnablePortClock(PORTD_IDX);

  /* Init board clock */

  BOARD_ClockInit();

}

Those inits are called once at the beginning of main(), so when ROM bootloader starts the app residing in flash then all the above code is of course executed.

LCD display is initialized correctly, but the counter is not incremented

2.When I sent any command from blhost to the board that has been working correctly (after reset) - everything stops and board does not respond anymore.

Thank you in advance for any suggestions!

0 Kudos

273 Views
bobpaddock
Senior Contributor III

Install some code to catch hardware faults that prints the address via a UART.  I expect you will find a your program is ending up in a non-existing fault handler so it looks dead to you.


There is also a bug, or at least I could never get it to work as documented, that you need to put this early in your code so you don't have to cycle power if you have FOPTS set for Flash and use NMI# as BOOT#:

  /*

   * Indicates the boot source, the boot source remains set until the

   * next System Reset or software can write logic one to clear the

   * corresponding mode bit.  While either bit is set, the NMI input

   * is disabled and the vector table is relocated to the ROM base

   * address at 0x1C00_0000. These bits should be cleared by writing

   * logic one before executing any code from either Flash or SRAM.

   */

  if( 0U != (RCM_MR & RCM_FM_FORCEROM_MASK) )

    {

      RCM_FM = 0U;

      RCM_MR = RCM_MR_BOOTROM_MASK;

    }


This is what I use for hardware fault handler:

/** @(#)fault_hard_iprint.c <04-Oct-2013 13:17:45 Bob Paddock>

*  \date Last Time-stamp:  <29-May-2015 15:58:13 bob p>

*

*  \file fault_hard_iprint.c

*  \brief  Hardware Fault Handler.

*

*  This overrides the weak linkage of the empty function found in

*  vectors.c.

*

* https://github.com/feabhas/CM3_Fault_Handler

* http://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/

* http://mcuoneclipse.com/2012/12/28/a-processor-expert-component-to-help-with-hard-faults/

*

*  Split from _startup.c from Andrew Payne.

*

*  Original code Copyright (c) 2012-2013 Andrew Payne <andy@payne.org>

*/

/*lint -save */

#include <stdio.h>      /* fiprintf() */

#include <inttypes.h>   /* PRIu32 */

/*

* If you don't want to use the PRI* macros, another approach for

* printing ANY integer type is to cast to intmax_t or uintmax_t and

* use "%jd" or %ju, respectively. This is especially useful for POSIX

* (or other OS) types that don't have PRI* macros defined, for

* instance off_t. -- http://stackoverflow.com/questions/3168275/printf-format-specifiers-for-uint32-t-and-size-t

*/

#include "compiler.h"

#include "fault_soft.h" /* Lockup with LED blink pattern after outputing message via fiprintf() */

#include "uart0.h"

#if 0

void HardFault_Handler_init( void );

void HardFault_Handler_init( void )

{

  uart0_init( 115200 );

}

#endif

/* The register frame pushed onto the stack during exceptions: */

typedef struct {

    uint32_t r0;

    uint32_t r1;

    uint32_t r2;

    uint32_t r3;

    uint32_t r12;

    uint32_t lr;

    void *pc;     /* Program counter is *after* the problem, the program counter has an odd address for ARM Thumb code */

    uint32_t psr;

} hw_stackframe_t;

/* Handle hard faults:  print debugging information and halt: */

void HardFault_Handler(void)  __attribute__((naked));

void HardFault_Handler(void)

{

  /* Set up arguments and invoke _HardFault_Handler(): */

  asm("mov  r0, lr\n"                   /* Arg 0 */

      "mrs  r1, psp\n"                  /* Arg 1 */

      "mrs  r2, msp\n"                  /* Arg 2 */

      "b    _hard_fault_handler\n");

}

void _hard_fault_handler( uint32_t const lr, void *psp, void *msp ) __attribute__(( naked, noreturn ));

void _hard_fault_handler( uint32_t const lr, void *psp, void *msp )

{

    hw_stackframe_t *frame;

    /* Find the active stack pointer (MSP or PSP): */

    if( 0U != (lr & 0x4) )

      {

        frame = psp;

      }

    else

      {

        frame = msp;

      }

#if 0 /* These registers are not on the M0+: */

  /*

   * Configurable Fault Status Register

   * Consists of MMSR, BFSR and UFSR

   */

  uint32_t volatile const _CFSR = (*((uint32_t volatile *)(0xE000ED28)));

  uint32_t volatile const _HFSR = (*((uint32_t volatile *)(0xE000ED2C))); /* Hard Fault Status Register */

  uint32_t volatile const _DFSR = (*((uint32_t volatile *)(0xE000ED30))); /* Debug Fault Status Register */

  uint32_t volatile const _AFSR = (*((uint32_t volatile *)(0xE000ED3C))); /* Auxiliary Fault Status Register */

  /*

   * Read the Fault Address Registers. These may not contain valid values.

   * Check BFARVALID/MMARVALID to see if they are valid values:

   */

  uint32_t volatile const _MMAR = (*((uint32_t volatile *)(0xE000ED34))); /* MemManage Fault Address Register */

  uint32_t volatile const _BFAR = (*((uint32_t volatile *)(0xE000ED38))); /* Bus Fault Address Register */

#endif

    fiprintf(

             stderr, "\r\n** HARD FAULT **\r\n  pc=%p\r\n  lr=0x%" PRIu32 "\r\n  msp=%p\r\n  psp=%p\r\n",

             frame->pc, frame->lr, msp, psp

            ) ;

    fault_soft_handler( 0x3F8UL);            /* Blink LED and halt */

}

/*lint -restore */

0 Kudos

273 Views
piotrcerba
Contributor III

Thank you for your answer Bob Paddock.

1. Putting this code at the beginning of my main() unfortunately did not help:

if( 0U != (RCM_MR & RCM_FM_FORCEROM_MASK) )

    {

      RCM_FM = 0U;

      RCM_MR = RCM_MR_BOOTROM_MASK;

    }

2.

My compiler.h is located (by pressing F3 in KDS) in SDK/usb/usb_core/include is it the correct one? It only has a couple of PACKED_STRUCT and PACKED_UNION

Besides I am missing

#include "fault_soft.h"

#include "uart0.h"

Can you provide them somehow? If not here, then could you please email those files to cerberus2006 <at> hotmail.com

3. Should I leave the HardFault_Handler in startup_MKL43Z4.S as it is, or replace it with

_hard_fault_handler

Thank you in advance!

0 Kudos