µTasker Forum

µTasker Forum => NXPTM M522XX, KINETIS and i.MX RT => Topic started by: kevinR on August 02, 2017, 04:49:48 PM

Title: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 02, 2017, 04:49:48 PM
I'm interested in the serial bootloader ported to the MK22FN1M0VLH12 (or very similar MK22FN1M0AVLH12).  The Blaze_K22 supported with uTasker uses the same micro, so under the config.h I un-commented #define BLAZE_K22.  I followed the quick start video for KDS, chose the "K_1M_128_Blaze.ld" linker.  When I compile, I receive the following error:

fatal error: widgets.h: No such file or directory   serial_loader.c   /uTaskerV1.4/Applications/uTaskerSerialBoot   line 59   C/C++ Problem

I'm not interested in supporting the Blaze and it's display (which I assume the widgets.h is for??).  Is there a way to proceed in building the serial bootloader for the MK22FN1M0VLH12 or should I start from a different process.

Thanks,
Kevin
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 02, 2017, 06:02:31 PM
Hi Kevin

If you execute \Applications\uTaskerSerialBoot\widgets.bat (double click on it) it will generate the missing "widgets.h" file from the bit maps in \Applications\uTaskerSerialBoot\Images. (Build also needs _NO_CHECK_QUEUE_INPUT commented out in config.h)

However, if you don't have the Blaze TFT connected it doesn't make any sense in using the graphics interface in the serial loader. In order to remove this simply comment out
#define SUPPORT_GLCD
and
#define SUPPORT_TOUCH_SCREEN
in the Blaze section of config.h
and then it will build without any TFT interface.

Out of interest, this is how the BLAZE Serial loader looks when running (shown in the simulator):

(http://www.uTasker.com/Images/blaze_loader_sim.png)

Regards

Mark
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 02, 2017, 06:33:59 PM
Mark, thank you for the fast reply.  Yes, I just saw those defines for the LCD and it now compiles.

I setup my P&E debugger to debug the project, but nothing appears to happen and no USB MSD device shows up. It looks like it is trying to launch the user app which is currently blank.  By default the debugger sets a breakpoint at main, but I didn't find this anywhere.  I'm new to uTasker, so I don't know where the entry point is for the project to debug it.

With my custom hardware, I don't have any dedicated boot pin so maybe this is my problem with the default configuration.  My plan was to alter the decision somewhere to enter the bootloader based upon reset source (Kinetis registers RCM_SRS0 and RCM_SRS1).  If the reset source is the reset pin (my hack for a bootloader pin) or a SW reset (my user app launches the bootloader by forcing a reset) then the bootloader should be entered.  Where is the decision currently made?

Thanks for any help!
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 02, 2017, 07:59:21 PM
Kevin

Make sure that USB_INTERFACE is enabled if you want USB loading (eg. USB_MSD_DEVICE_LOADER type).

The entry point tends to be (exceptions may apply for certain IDEs - such as IAR which enters at static void disable_watchdog(void))


// Main entry for the target code
//
extern int main(void)
{


This will be hit every time, even if the loader jumps straight to the application.
Take a look at https://www.youtube.com/watch?v=bilc_4Cr7eo&index=13&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q which shows the serial loader being used with KDS (towards the end it shows the debugger connecting).

The blaze project forces the boot loader and waits a few seconds to see whether the touch screen is tapped, else it jumps to the application.
Without the touch screen part it will always boot into the mode and stay there as it is...

    #define FORCE_BOOT()            1                                    // always start the boot loader

You can see how other HW uses this to decide whether to jump or not (usually sampling a port state).

There is a small mail-box defined at the top of stack that can be used by an application to tell the boot loader to not jump.
Eg.
#define FORCE_BOOT() (((RCM_SRS1 & RCM_SRS1_SW) != 0) && (*BOOT_MAIL_BOX == 0x1234))

The application sets the pattern and command a software reset and then it will go to the loader mode.
BOOT_MAIL_BOX is the top 2 bytes of SRAM so the application should not use these if possible. There are others entries in the area used by uTasker applications but this may be the only one of interest in this case.

Regards

Mark




Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 03, 2017, 03:00:42 PM
Thank you for the tips about how to enter the bootloader via software.  At the moment, I'm still battling trying to debug the bootloader.  Attached is a screenshot showing what happens when I run the debugger.  Can you make sense of what I'm seeing?
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 03, 2017, 04:25:33 PM
What about the clocking? I have a 16 MHz crystal and I specify 10 pF load via the Kinetis registry.  Does the Blaze_K22 bootloader need to set this up or can it run independently?  A while back when I setup this micro I thought it required an external clock for USB.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 03, 2017, 08:13:25 PM
Kevin

The Blaze uses this setup:

#elif defined BLAZE_K22
    #define OSC_LOW_GAIN_MODE                                            // oscillator without feedback resistor or load capacitors so use low gain mode
    #define CRYSTAL_FREQUENCY    16000000                                // 16 MHz crystal
    #define _EXTERNAL_CLOCK      CRYSTAL_FREQUENCY
    #define CLOCK_DIV            4                                       // input must be divided to 2MHz..4MHz range (/1 to /24 for 120MHz parts)
    #define CLOCK_MUL            30                                      // the PLL multiplication factor to achieve operating frequency of 120MHz (x24 to x55 possible)
    #define FLEX_CLOCK_DIVIDE    3                                       // 120/3 to give 40MHz
    #define FLASH_CLOCK_DIVIDE   5                                       // 120/5 to give 24MHz
    #define USB_CLOCK_GENERATED_INTERNALLY                               // use USB clock from internal source rather than external pin - 120MHz is suitable

The USB clock is derived from the 120MHz PLL and doesn't need an external one.
One can choose between OSC_LOW_GAIN_MODE enabled or not. When enabled the circuit have no caps or loading. If there is a feedback resistor n cap loading this usually needs to be disabled so that high gain mode is used.
If one doesn't work use the other (if it doesn't match the 16MHz crystal may not start).

The controllable loading is not used but the application can adjust these or change setting if it wants after the boot loader has started it.

Regards

Mark

Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 03, 2017, 08:17:13 PM
Kevin

After loading check the memory at 0x00000000 to verify that it matches the bin file (it starts with the SP and PC values).
From the screen shot it looks like no code is being loaded(?)

Beware also that it is never possible to step the initial code that enables or disables the watchdog so this has to be run over and not stepped though (due to HW watchdog behavior).

Regards

Mark
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 03, 2017, 10:24:24 PM
I'm still stuck. I've tried directly flashing the srec, hex and bin files from "uTasker-Kinetis\uTaskerSerialLoader_FLASH", but maybe I'm not doing something right.  Attached are some screenshots of my debug configuration.  Does anything look wrong? I created a scratch workspace, but that didn't help.  It also says it can't find the source in the debugger perspective.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 03, 2017, 10:58:15 PM
Kevin

I checked all of the screen shots and don't see anything that is not correct. Just clicking the debug button should connect, program and it should then stop at the entry address.

Although I don't think that it would explain debugging issues check that the compiler target is set to Cortex-M4 (optionally with HW FPU) and that the linker script file chosen matches the device.
Do you have a standard reference board for cross-checking too, in case it is HW related?

If you would like to send a contact request to my Skype address we could have a quick look together using remote desktop sine I don't have any more suggestions at the moment to explain why the debugger has difficulties.

Regards

Mark
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 09, 2017, 08:37:36 PM
Update: I'm able to debug the serial bootloader now.  I tried "K_1M_128.ld" instead of "K_1M_128_Blaze.ld" for the linker and now it works.  I'm trying to find my away around the code now, but at least I can step through and see where it goes.  I don't see any MSD devices.

As an aside, I have custom hardware and there is no standard NXP development boards for this micro that I know of.  When I flash my normal FW onto the board it responds fine as a USB CDC device, so I think the HW checks out.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 09, 2017, 09:24:16 PM
I am still trying to digest how uTasker works, but I think fnTaskUSB() from usb_device_loader.c needs to be called somewhere, but when I set a breakpoint in this function it is never called.  It looks like uTaskerSchedule() is called in a while loop in kinetis.c, but it isn't doing anything that I can see.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 10, 2017, 12:01:24 AM
Kevin

K_1M_128.ld is correct. The Blaze linker script version is linked to an offset (0x10000) so that it can be loaded using the Blaze's internal loader and so can't run when stand-alone.

This is how the system works (when set up for USB-MSD).
1. After disabling (or configuring the watchdog and the clock settings) it calls fnUserHWInit() in serial_loader. Here it checks whether there is application code to jump to or whether the user is forcing the loader (eg. by holding a switch at reset). Make sure that the flash is erased when starting so that it doesn't immediately jump to something (that can't run) or force the loader mode [see FORCE_BOOT() for decision]
2. Assuming it stays in the loader it calls
        fnInitialiseHeap(ctOurHeap, fnGetHeapStart());                   // create heap
   uTaskerStart((UTASKTABLEINIT *)ctTaskTable, ctNodes, PHYSICAL_QUEUES); // start the operating system

which will allocate HEAP memory and configure the tasks that will be run, plus start the TICK timer.
3. Now it will start a forever loop calling
uTaskerSchedule()
which will schedule the tasks "when they need to run".
4. ptTaskTable->ptrTaskEntry(ptTaskTable);                      // call the task
is the task call. If you put a break point on this you can see every task call.
5. Generally the tasks will be called like this:
fnTaskWatchdog() - toggles LED and retriggers the watchdog (if enabled)
fnTaskUSB() - initialises the USB device interface [indeed in usb_device_loader.c]
fnTaskWatchdog() (after 100ms)
fnApplication() - initialised UART (if enabled)
fnTaskWatchdog() (after 100ms)
fnTaskWatchdog() (after 100ms)
fnTaskWatchdog() (after 100ms)
etc.

5. The USB task will be called again only after the USB device driver has completed enumeration [interrupt driven] (when connected to a USB host)

If you check this sequence you may identify where a deviation is in your case.

Good luck

Regards

Mark






Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 15, 2017, 04:16:05 AM
I finally had some time on this again.  I think I see how the tasks work, and I can set breakpoints in fnTaskWatchdog() and see it is serviced.  I reconfigured the watchdog LED to my hardware and it now blinks.  I trust that more than the debugger :).

fnTaskUSB() is still never serviced which I guess means the firmware is not enumerating for some reason.  I know the USB hardware works with my user firmware, so I wonder what isn't getting setup correctly.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 15, 2017, 02:03:03 PM
Kevin

The USB task is called once to initialise the USB interface.
It is called a second time only after enumeration.

I have just checked again how the Blaze configuration operates and see the following, which is a little different to normal. It only actually enables the USB interface when the user taps on the display!

This is controlled in TaskConfig.h as follows:

        #if defined BLAZE_K22
    { "usb",       fnTaskUSB,      SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP }, // USB (application) task is only started if commanded
        #else
    { "usb",       fnTaskUSB,      SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_ACTIVATE}, // USB (application) task
        #endif


Notice that the USB task is not started (it will be later started from the code that detects the user taping on the display). Therefore, since you don't have a display, you will need to change this so that the task is indeed started

For example, change the define decision to
#if defined BLAZE_K22 && defined SUPPORT_TOUCH_SCREEN
which will then cause the USB task to be started immediately if the touch display is not enabled.

This will very probably solve your problem!

Regards

Mark

Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 15, 2017, 06:43:03 PM
Fantastic! That did the trick.  Now I see the MSD device showing up.  Thanks for finding this.

Now I just need to modify my user app to start at 0x8080.  Is that correct?  I'm using Processor Expert, and I've found where to change the parameters for the generated linker.  I assume I just add 0x8080 to both the m_interrupts and m_text?  Here is what the generated linker put out:

Code: [Select]
MEMORY {
  m_interrupts (RX) : ORIGIN = 0x00008208, LENGTH = 0x00000188
  m_text      (RX) : ORIGIN = 0x00008490, LENGTH = 0x000F7B70
  m_data      (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x00010000
  m_data_20000000 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00010000
  m_cfmprotrom  (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
}

I also setup my project to output raw binary bin file.  At present I can copy the .bin file to the MSD and the file shows up, but it does not run after I power cycle the board.  The loader shows back up empty.

I saw your article (http://www.utasker.com/forum/index.php?topic=1869.0), and so I think I may be doing something wrong with the vector table address and 512 byte boundary.  Can I make the start at 0x8000 instead or does this cause problems.  Otherwise, I'm not following where I place the code to copy the vector table to SRAM.

By the way, for some reason I cannot get the bootloader to run on a cold power up.  I have to toggle the reset line before it comes up.  I have not done anything yet to the FORCE_BOOT().  It is always 1.  I suspect it has to do with not setting up the crystal loads, but I can test that.

Thank you again for you help!






Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 15, 2017, 06:53:28 PM
I think I made a mistake below.  I really wanted m_interrupts to start at 0x8080 and not 0x8208 as shown (I added 0x188 to 0x8080).  This still has the same behavior as before.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 15, 2017, 08:04:53 PM
Kevin

It is correct that m_interrupts needs too be at 0x8080.

m_cfmprotrom  (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
is however wrong because it will be located before the reset vector.

This area is in fact of no use for an application working with a loader (the loader occupies this space and defines the Flash configuration parameters) and so you may be able to remove it from the code to get rid of it. If not, try to locate it between the reset vectors and the application. If you can avoid PE from overwriting the linker script you can also edit it manually - this should be what you need:

MEMORY {
  m_interrupts (RX) : ORIGIN = 0x00008080, LENGTH = 0x00000188
  m_cfmprotrom  (RX) : ORIGIN = 0x00008208, LENGTH = 0x00000010
  m_text      (RX) : ORIGIN = 0x00008218, LENGTH = 0x000F7DE8
  m_data      (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x00010000
  m_data_20000000 (RW) : ORIGIN = 0x20000000, LENGTH = 0x00010000
}


Usually a project will have an option to run vectors from Flash or in SRAM - if PE can't do this you can add a memcpy() to copy 0x188 bytes from 0x8080 to 0x1fff0000 and then write the Vector Table Offset Register: VECTOR_TABLE_OFFSET_REG = 0x1fff0000; [*(unsigned long *)0xe000ed08 = 0x1fff0000]

In order to keep vectors in Flash you can change the start address to 0x8200 (instead of 0x8080) and change
#define ROOT_FILE_ENTRIES         4                                  // when USB MSD loader this many directory entries are set to the start of FLASH - the application start is shifted by this amount x 32 bytes
to
#define ROOT_FILE_ENTRIES         16                                  // when USB MSD loader this many directory entries are set to the start of FLASH - the application start is shifted by this amount x 32 bytes
to adjust it in the serial loader.
This is necessary because the vector table must be 512 byte aligned for all the interrupts to be able to operate correctly.

Regards

Mark

Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 15, 2017, 09:45:48 PM
Alright, we're making great progress.  Thanks again for the guidance.  I chose to move the address out to 0x8200 to make things easier for me.  I manually deleted the m_cfmprotrom per your advice.  I can now load my .bin file to the MSD, and with FORCE_BOOT() set to 0, it will automatically launch my app after copying!  I'll play with changing FORCE_BOOT() later.

I'm still working on the startup issue, however.  My thought is it is a problem with the crystal configuration.  I'm trying to understand how the clock is configured in kinetis_K_CLOCK.h.  I'm wondering if I need to add the following somewhere to add the 10 pF of loading (2pF+8pF).

Code: [Select]
OSC_CR = (OSC_CR_ERCLKEN_MASK | OSC_CR_SC2P_MASK | OSC_CR_SC8P_MASK);
On Power-On-Reset, I'm not seeing anything on the clock lines with a scope.  When I cycle the reset pin, it does something to jar it and it oscillates at the 16 MHz.
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 15, 2017, 10:04:31 PM
I see my code just has a slightly different definition for the OSC_CR register.  You have OSC0_CR instead.  I added the following loading to this line: 

Code: [Select]
OSC0_CR = (OSC_CR_ERCLKEN | OSC_CR_EREFSTEN | OSC_CR_SC2P | OSC_CR_SC8P);
(By the way, I found a typo for OSC_CR_SC8P.  It was originally OSC_CR_SC18P)

This still didn't do anything.  What I'm curious about is why KDS shows this line as inactive code by #if defined FLL_FACTOR || defined RUN_FROM_EXTERNAL_CLOCK.  I tried right after this inactive code the same line, but it doesn't work.

Looking at my lab supply that is powering the board, it draws around 12 mA when normally running after resetting.  On power on reset, the current draw is only about 1 mA.  It seems like it is stuck somewhere simple...
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: mark on August 16, 2017, 01:00:01 AM
Kevin

There is a define
OSC_LOW_GAIN_MODE
which is used by the Blaze since its crystal circuit has no loading (neither caps nor feedback resistor)
Try removing this, especially if you have R/C components in the hardware.

With the wrong setting the crystal often won't start-up. Sometimes touching the crystal is enough to get it going and sometimes not (when wrong).

This setting controls whether MCG_C2_HGO is set in MCG_C2 or not.
The place that the code gets stuck if not right is at
    while ((MCG_S & MCG_S_OSCINIT) == 0) {                               // loop until the crystal source has been selected

Regards

Mark
Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 16, 2017, 04:59:57 PM
It was little painful, but I think I found the issue.  My code disables NMI CPU interrupts (I think by disabling MCM_ETBCC bits RSPT and CNTEN) and sets the NMI_DIS bit in the FOPT for PTA4.  I use this pin for GPIO with an RC pull-up to 3.3V.  So on power-up the cap keeps this pulled low through reset.  When I bypass the resistor and tie PTA4 to 3.3V, the micro always boots!

I also disable the EzPort by setting EZPORT_DIS bit (also in FOPT) as well which I think may be equally important in my case.  I'm starting to recall this issue some years back.  I guess I'm re-discovering it.

So, can you kindly show me where I would set the flash configuration fields in uTasker.

Title: Re: MK22FN1M0VLH12 port using Blaze_K22
Post by: kevinR on August 16, 2017, 05:25:11 PM
I found it.  It was actually the EZPORT that needed to be disabled as you already had the NMI disabled.  It is effected by the same pin (PTA4).

I changed:
#define KINETIS_FLASH_CONFIGURATION_NONVOL_OPTION  (FTFL_FOPT_EZPORT_ENABLED | FTFL_FOPT_LPBOOT_NORMAL | FTFL_FOPT_NMI_DISABLED)
to
#define KINETIS_FLASH_CONFIGURATION_NONVOL_OPTION  (FTFL_FOPT_EZPORT_DISABLED | FTFL_FOPT_LPBOOT_NORMAL | FTFL_FOPT_NMI_DISABLED)

Now all is well for booting every time on power up!

Now I'll just cleanup the FORCE_BOOT() decision and I think I'm done.  Thanks for the help, Mark!