Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - mark

Pages: [1] 2 3 ... 219
1
Hi

Example: When peripherals are enabled (gated) and then used it is possible that between gating and it being ready there is a delay (in the synchronisation of clock domains) that means that the code using the peripheral will use it slightly too early.
What happens is that there is a hard fault. If the hard fault lands in a forever loop it fails. If the hard fault simply returns it then repeats (and works) and all is fine and it continues.
That is, there can be 'temporary' hard faults that are not really critical.
Often they can be avoided by using instruction / data barrier commands like

asm volatile ("dsb 0xf":::"memory");
asm volatile ("isb 0xf":::"memory");


which cause the processor to wait until the previous peripheral write operations have completed but this can be fiddly.

What I do is use a very simple hard fault handler that counts how often it happens, doesn't result in a loop and recovers (if it is a 'real'/serious hard fault it results in a hard fault interrupt loop anyway, which is very easy to debug as you just need to connect with a debugger and you see the exact code that is faulting (over and over again)).


volatile unsigned long ulHardFaultCounter = 0;
// Serious error interrupts
//
static void irq_hard_fault(void)
{
    ulHardFaultCounter++;                                                // hard faults are often recoverable so we count how many were detected for statistical reasons
}


I can always check the counter value to see whether it does every occasionally happen. If I prefer to 'clean' it up so that it doesn't I just set a break point on the increment line, let it run and see exactly where it takes place and then, if I want, I can add a barrier instruction (or similar - eg. adding some other code before accessing usually works) to exclude it. Recoverable hard faults are however not really worth worrying about as they have no negative side effects (that I ever experienced).

Regards

Mark

2
Hi

Make sure that you have switched the repo. to V2.0.0 so that you are using newest source (master source will have linker script files that stopped working with newest GCC versions).

When using MCUXpresso the managed build is not used (where the internal settings are configured) but instead the linker script is entered (see the MCUXpresso guide document or video).

I wouldn't bother changing 8M Flash to 4Meg since it won't change anything. It would just give you an error in case >4 Meg was actually used.

Regards

Mark

P.S: Below is the content of \Applications\uTaskerV1.4\GNU_iMX\iMX_RT_10XX_FlexSPI_NOR.ld as reference


======================================================================

/* iMX_RT_10XX_FlexSPI_NOR.ld - compatible with MCUXpresso > V11.4        */
/* GCC memory file for the iMX RT 10XX - for use with the uTasker project */
/* Use when running from FlexSPI Flash (total up to 512k CPU SRAM)        */


_HeapSize = 0x0;                                    /* uTasker project usually does not use library heap */
_StackSize = 0x0;                                   /* uTasker project organises stack at run time       */

MEMORY
{
  /* Define each memory region */
  BOARD_FLASH (rx) : ORIGIN = 0x60000000, LENGTH = 0x800000 /* 8M bytes (alias Flash) */ 
  SRAM_DTC (rwx) : ORIGIN = 0x20000300, LENGTH = 0x80000-0x0300 /* up to 512K bytes (alias RAM) - with vectors at the start */ 
  SRAM_ITC (rwx) : ORIGIN = 0x0, LENGTH = 0x80000 /* up to 512K bytes (alias RAM2) */ 
  SRAM_OC (rwx) : ORIGIN = 0x20200000, LENGTH = 0xc0000 /* 768K bytes (alias RAM3) */ 
  BOARD_SDRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x1e00000 /* 30M bytes (alias RAM4) */ 
  NCACHE_REGION (rwx) : ORIGIN = 0x81e00000, LENGTH = 0x200000 /* 2M bytes (alias RAM5) */ 
}

  /* Define a symbol for the top of each memory region */
  __base_BOARD_FLASH = 0x60000000  ; /* BOARD_FLASH */ 
  __base_Flash = 0x60000000 ; /* Flash */ 
  __top_BOARD_FLASH = 0x60000000 + 0x800000 ; /* 8M bytes */ 
  __top_Flash = 0x60000000 + 0x800000 ; /* 8M bytes */ 
  __base_SRAM_DTC = 0x20000300  ; /* SRAM_DTC */ 
  __base_RAM = 0x20000000 ; /* RAM */ 
  __top_SRAM_DTC = 0x20000300 + 0x80000 - 0x0300 ; /* up to 512k bytes */ 
  __top_RAM = 0x20000000 + 0x80000 ; /* up to 512k bytes */ 
  __base_SRAM_ITC = 0x0  ; /* SRAM_ITC */ 
  __base_RAM2 = 0x0 ; /* RAM2 */ 
  __top_SRAM_ITC = 0x0 + 0x80000 ; /* up to 512K bytes */ 
  __top_RAM2 = 0x0 + 0x80000 ; /* up to 512K bytes */ 
  __base_SRAM_OC = 0x20200000  ; /* SRAM_OC */ 
  __base_RAM3 = 0x20200000 ; /* RAM3 */ 
  __top_SRAM_OC = 0x20200000 + 0xc0000 ; /* 768K bytes */ 
  __top_RAM3 = 0x20200000 + 0xc0000 ; /* 768K bytes */ 
  __base_BOARD_SDRAM = 0x80000000  ; /* BOARD_SDRAM */ 
  __base_RAM4 = 0x80000000 ; /* RAM4 */ 
  __top_BOARD_SDRAM = 0x80000000 + 0x1e00000 ; /* 30M bytes */ 
  __top_RAM4 = 0x80000000 + 0x1e00000 ; /* 30M bytes */ 
  __base_NCACHE_REGION = 0x81e00000  ; /* NCACHE_REGION */ 
  __base_RAM5 = 0x81e00000 ; /* RAM5 */ 
  __top_NCACHE_REGION = 0x81e00000 + 0x200000 ; /* 2M bytes */ 
  __top_RAM5 = 0x81e00000 + 0x200000 ; /* 2M bytes */ 



ENTRY(__vector_table)

SECTIONS
{
     /* Image Vector Table and Boot Data for booting from external flash */
    .boot_hdr : ALIGN(4)
    {
        FILL(0xff)
        __boot_hdr_start__ = ABSOLUTE(.) ;
        KEEP(*(.boot_hdr.conf))
        . = 0x1000 ;
        KEEP(*(.boot_hdr.ivt))
        . = 0x1020 ;
        KEEP(*(.boot_hdr.boot_data))
        . = 0x1030 ;
        KEEP(*(.boot_hdr.dcd_data))
        . = 0x1fb0 ;
        KEEP(*(.boot_hdr.key))
        . = 0x1fe0 ;
        KEEP(*(.boot_hdr.init))
        __boot_hdr_end__ = ABSOLUTE(.) ;
        . = 0x2000 ;
    } >BOARD_FLASH

    /* MAIN TEXT SECTION */
    .text : ALIGN(4)
    {
        FILL(0xff)
        __vectors_start__ = ABSOLUTE(.) ;
        KEEP(*(.vectors))
        /* Global Section Table */
        . = ALIGN(4) ;
        __section_table_start = .;
        __data_section_table = .;
        LONG(LOADADDR(.data));
        LONG(    ADDR(.data));
        LONG(  SIZEOF(.data));
        LONG(LOADADDR(.data_RAM2));
        LONG(    ADDR(.data_RAM2));
        LONG(  SIZEOF(.data_RAM2));
        LONG(LOADADDR(.data_RAM3));
        LONG(    ADDR(.data_RAM3));
        LONG(  SIZEOF(.data_RAM3));
        LONG(LOADADDR(.data_RAM4));
        LONG(    ADDR(.data_RAM4));
        LONG(  SIZEOF(.data_RAM4));
        LONG(LOADADDR(.data_RAM5));
        LONG(    ADDR(.data_RAM5));
        LONG(  SIZEOF(.data_RAM5));
        __data_section_table_end = .;
        __bss_section_table = .;
        LONG(    ADDR(.bss));
        LONG(  SIZEOF(.bss));
        LONG(    ADDR(.bss_RAM2));
        LONG(  SIZEOF(.bss_RAM2));
        LONG(    ADDR(.bss_RAM3));
        LONG(  SIZEOF(.bss_RAM3));
        LONG(    ADDR(.bss_RAM4));
        LONG(  SIZEOF(.bss_RAM4));
        LONG(    ADDR(.bss_RAM5));
        LONG(  SIZEOF(.bss_RAM5));
        __bss_section_table_end = .;
        __section_table_end = . ;
        /* End of Global Section Table */

        *(.after_vectors*)

       *(.text*)
       *(.rodata .rodata.* .constdata .constdata.*)
       . = ALIGN(4);
    } > BOARD_FLASH
    /*
     * for exception handling/unwind - some Newlib functions (in common
     * with C++ and STDC++) use this.
     */
    .ARM.extab : ALIGN(4)
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > BOARD_FLASH

    .ARM.exidx : ALIGN(4)
    {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } > BOARD_FLASH
 
    _etext = .;
       
    /* DATA section for SRAM_ITC */

    .data_RAM2 : ALIGN(4)
    {
        FILL(0xff)
        PROVIDE(__start_data_RAM2 = .) ;
        PROVIDE(__start_data_SRAM_ITC = .) ;
        *(.ramfunc.$RAM2)
        *(.ramfunc.$SRAM_ITC)
        *(.data.$RAM2)
        *(.data.$SRAM_ITC)
        *(.data.$RAM2.*)
        *(.data.$SRAM_ITC.*)
        . = ALIGN(4) ;
        PROVIDE(__end_data_RAM2 = .) ;
        PROVIDE(__end_data_SRAM_ITC = .) ;
     } > SRAM_ITC AT>BOARD_FLASH

    /* DATA section for SRAM_OC */

    .data_RAM3 : ALIGN(4)
    {
        FILL(0xff)
        PROVIDE(__start_data_RAM3 = .) ;
        PROVIDE(__start_data_SRAM_OC = .) ;
        *(.ramfunc.$RAM3)
        *(.ramfunc.$SRAM_OC)
        *(.data.$RAM3)
        *(.data.$SRAM_OC)
        *(.data.$RAM3.*)
        *(.data.$SRAM_OC.*)
        . = ALIGN(4) ;
        PROVIDE(__end_data_RAM3 = .) ;
        PROVIDE(__end_data_SRAM_OC = .) ;
     } > SRAM_OC AT>BOARD_FLASH

    /* DATA section for BOARD_SDRAM */

    .data_RAM4 : ALIGN(4)
    {
        FILL(0xff)
        PROVIDE(__start_data_RAM4 = .) ;
        PROVIDE(__start_data_BOARD_SDRAM = .) ;
        *(.ramfunc.$RAM4)
        *(.ramfunc.$BOARD_SDRAM)
        *(.data.$RAM4)
        *(.data.$BOARD_SDRAM)
        *(.data.$RAM4.*)
        *(.data.$BOARD_SDRAM.*)
        . = ALIGN(4) ;
        PROVIDE(__end_data_RAM4 = .) ;
        PROVIDE(__end_data_BOARD_SDRAM = .) ;
     } > BOARD_SDRAM AT>BOARD_FLASH

    /* DATA section for NCACHE_REGION */

    .data_RAM5 : ALIGN(4)
    {
        FILL(0xff)
        PROVIDE(__start_data_RAM5 = .) ;
        PROVIDE(__start_data_NCACHE_REGION = .) ;
        *(.ramfunc.$RAM5)
        *(.ramfunc.$NCACHE_REGION)
        *(.data.$RAM5)
        *(.data.$NCACHE_REGION)
        *(.data.$RAM5.*)
        *(.data.$NCACHE_REGION.*)
        . = ALIGN(4) ;
        PROVIDE(__end_data_RAM5 = .) ;
        PROVIDE(__end_data_NCACHE_REGION = .) ;
     } > NCACHE_REGION AT>BOARD_FLASH

    /* MAIN DATA SECTION */
    .uninit_RESERVED (NOLOAD) : ALIGN(4)
    {
        _start_uninit_RESERVED = .;
        KEEP(*(.bss.$RESERVED*))
       . = ALIGN(4) ;
        _end_uninit_RESERVED = .;
    } > SRAM_DTC AT> SRAM_DTC

    /* Main DATA section (SRAM_DTC) */
    .data : ALIGN(4)
    {
       FILL(0xff)
       _data = . ;
       PROVIDE(__start_data_RAM = .) ;
       PROVIDE(__start_data_SRAM_DTC = .) ;
       *(vtable)
       *(.ramfunc*)
       KEEP(*(CodeQuickAccess))
       KEEP(*(DataQuickAccess))
       *(RamFunction)
       *(NonCacheable.init)
       *(.data*)
       . = ALIGN(4) ;
       _edata = . ;
       PROVIDE(__end_data_RAM = .) ;
       PROVIDE(__end_data_SRAM_DTC = .) ;
    } > SRAM_DTC AT>BOARD_FLASH

    /* BSS section for SRAM_ITC */
    .bss_RAM2 : ALIGN(4)
    {
       PROVIDE(__start_bss_RAM2 = .) ;
       PROVIDE(__start_bss_SRAM_ITC = .) ;
       *(.bss.$RAM2)
       *(.bss.$SRAM_ITC)
       *(.bss.$RAM2.*)
       *(.bss.$SRAM_ITC.*)
       . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
       PROVIDE(__end_bss_RAM2 = .) ;
       PROVIDE(__end_bss_SRAM_ITC = .) ;
    } > SRAM_ITC AT> SRAM_ITC

    /* BSS section for SRAM_OC */
    .bss_RAM3 : ALIGN(4)
    {
       PROVIDE(__start_bss_RAM3 = .) ;
       PROVIDE(__start_bss_SRAM_OC = .) ;
       *(.bss.$RAM3)
       *(.bss.$SRAM_OC)
       *(.bss.$RAM3.*)
       *(.bss.$SRAM_OC.*)
       . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
       PROVIDE(__end_bss_RAM3 = .) ;
       PROVIDE(__end_bss_SRAM_OC = .) ;
    } > SRAM_OC AT> SRAM_OC

    /* BSS section for BOARD_SDRAM */
    .bss_RAM4 : ALIGN(4)
    {
       PROVIDE(__start_bss_RAM4 = .) ;
       PROVIDE(__start_bss_BOARD_SDRAM = .) ;
       *(.bss.$RAM4)
       *(.bss.$BOARD_SDRAM)
       *(.bss.$RAM4.*)
       *(.bss.$BOARD_SDRAM.*)
       . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
       PROVIDE(__end_bss_RAM4 = .) ;
       PROVIDE(__end_bss_BOARD_SDRAM = .) ;
    } > BOARD_SDRAM AT> BOARD_SDRAM

    /* BSS section for NCACHE_REGION */
    .bss_RAM5 : ALIGN(4)
    {
       PROVIDE(__start_bss_RAM5 = .) ;
       PROVIDE(__start_bss_NCACHE_REGION = .) ;
       *(.bss.$RAM5)
       *(.bss.$NCACHE_REGION)
       *(.bss.$RAM5.*)
       *(.bss.$NCACHE_REGION.*)
       . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
       PROVIDE(__end_bss_RAM5 = .) ;
       PROVIDE(__end_bss_NCACHE_REGION = .) ;
    } > NCACHE_REGION AT> NCACHE_REGION

    /* MAIN BSS SECTION */
    .bss : ALIGN(4)
    {
        _bss = .;
        PROVIDE(__start_bss_RAM = .) ;
        PROVIDE(__start_bss_SRAM_DTC = .) ;
       *(NonCacheable)
        *(.bss*)
        *(COMMON)
        . = ALIGN(4) ;
        _ebss = .;
        PROVIDE(__end_bss_RAM = .) ;
        PROVIDE(__end_bss_SRAM_DTC = .) ;
        PROVIDE(end = .);
    } > SRAM_DTC AT> SRAM_DTC

    /* NOINIT section for SRAM_ITC */
    .noinit_RAM2 (NOLOAD) : ALIGN(4)
    {
       PROVIDE(__start_noinit_RAM2 = .) ;
       PROVIDE(__start_noinit_SRAM_ITC = .) ;
       *(.noinit.$RAM2)
       *(.noinit.$SRAM_ITC)
       *(.noinit.$RAM2.*)
       *(.noinit.$SRAM_ITC.*)
       . = ALIGN(4) ;
       PROVIDE(__end_noinit_RAM2 = .) ;
       PROVIDE(__end_noinit_SRAM_ITC = .) ;
    } > SRAM_ITC AT> SRAM_ITC

    /* NOINIT section for SRAM_OC */
    .noinit_RAM3 (NOLOAD) : ALIGN(4)
    {
       PROVIDE(__start_noinit_RAM3 = .) ;
       PROVIDE(__start_noinit_SRAM_OC = .) ;
       *(.noinit.$RAM3)
       *(.noinit.$SRAM_OC)
       *(.noinit.$RAM3.*)
       *(.noinit.$SRAM_OC.*)
       . = ALIGN(4) ;
       PROVIDE(__end_noinit_RAM3 = .) ;
       PROVIDE(__end_noinit_SRAM_OC = .) ;
    } > SRAM_OC AT> SRAM_OC

    /* NOINIT section for BOARD_SDRAM */
    .noinit_RAM4 (NOLOAD) : ALIGN(4)
    {
       PROVIDE(__start_noinit_RAM4 = .) ;
       PROVIDE(__start_noinit_BOARD_SDRAM = .) ;
       *(.noinit.$RAM4)
       *(.noinit.$BOARD_SDRAM)
       *(.noinit.$RAM4.*)
       *(.noinit.$BOARD_SDRAM.*)
       . = ALIGN(4) ;
       PROVIDE(__end_noinit_RAM4 = .) ;
       PROVIDE(__end_noinit_BOARD_SDRAM = .) ;
    } > BOARD_SDRAM AT> BOARD_SDRAM

    /* NOINIT section for NCACHE_REGION */
    .noinit_RAM5 (NOLOAD) : ALIGN(4)
    {
       PROVIDE(__start_noinit_RAM5 = .) ;
       PROVIDE(__start_noinit_NCACHE_REGION = .) ;
       *(.noinit.$RAM5)
       *(.noinit.$NCACHE_REGION)
       *(.noinit.$RAM5.*)
       *(.noinit.$NCACHE_REGION.*)
       . = ALIGN(4) ;
       PROVIDE(__end_noinit_RAM5 = .) ;
       PROVIDE(__end_noinit_NCACHE_REGION = .) ;
    } > NCACHE_REGION AT> NCACHE_REGION

    /* DEFAULT NOINIT SECTION */
    .noinit (NOLOAD): ALIGN(4)
    {
        _noinit = .;
        PROVIDE(__start_noinit_RAM = .) ;
        PROVIDE(__start_noinit_SRAM_DTC = .) ;
        *(.noinit*)
         . = ALIGN(4) ;
        _end_noinit = .;
       PROVIDE(__end_noinit_RAM = .) ;
       PROVIDE(__end_noinit_SRAM_DTC = .) ;       
    } > SRAM_DTC AT> SRAM_DTC

    /* Reserve and place Heap within memory map */
    .heap (NOLOAD) :  ALIGN(4)
    {
        _pvHeapStart = .;
        . += _HeapSize;
        . = ALIGN(4);
        _pvHeapLimit = .;
    } > SRAM_DTC

     /* Reserve space in memory for Stack */
    .heap2stackfill (NOLOAD) :
    {
        . += _StackSize;
    } > SRAM_DTC
    /* Locate actual Stack in memory map */
    .stack ORIGIN(SRAM_DTC) + LENGTH(SRAM_DTC) - _StackSize - 0 (NOLOAD) :  ALIGN(4)
    {
        _vStackBase = .;
        . = ALIGN(4);
        _vStackTop = . + _StackSize;
    } > SRAM_DTC

    /* Provide basic symbols giving location and size of main text
     * block, including initial values of RW data sections. Note that
     * these will need extending to give a complete picture with
     * complex images (e.g multiple Flash banks).
     */
    _image_start = LOADADDR(.text);
    _image_end = LOADADDR(.data) + SIZEOF(.data);
    _image_size = _image_end - _image_start;

    /* For compatibility with uTasker names */
    /*                                      */
    __data_start__ = _start_uninit_RESERVED;
    __data_end__ = __data_start__ + SIZEOF(.data);
    __data_load_start__ = LOADADDR (.data);
    __bss_start__ = __start_bss_RAM;
    __bss_end__ = __start_bss_RAM + SIZEOF(.bss);
    __heap_end__ = _pvHeapLimit;
}

3
Bill

Please use https://www.utasker.com/docs/iMX/GCC.pdf as guide to preparing the header and setting the necessary link address for any project.
If you don't find the details there try also https://www.utasker.com/docs/iMX/MCUXpresso.pdf as it may be a bit more 'foreign' application oriented.

Finally use the check-list in the appendix of https://www.utasker.com/docs/uTasker/uTaskerSerialLoader.pdf in case of problems.

Regards

Mark

4
µTasker general / TeraTerm -> changing serial COM ports
« on: February 09, 2026, 01:44:26 AM »
Hi All

I recently upgraded TeraTerm from V4.106, which I was using successfully for a few years, to V5.5.2 and had an issue that was not obvious to solve.

The first thing that I did was to save my COM port setup for use with a certain HW connection (Baud rate and COM port used) so that it always stated with it. That works fine.
But I found that I couldn't connect to any other COM ports and I also couldn't connect to virtual COM ports - TeraTerm remained disconnected.

Initially I assumed some problem with virtual COM ports (which I had also just set up and was trying to confirm with the new TeraTerm version) and so I experimented with installing and de-installing these but without any improvement.

It turns out that newer versions of TeraTerm require a different method when ports are changed:
- it is not possible to start TeraTerm with a pre-defined COM port setting (in its TERATERM.INI) and subsequently change it to another COM port using "Setup | Serial port..."
- to do this these steps are now needed:
- - "File | Disconnect"
- - "File | New connection..."
- - "Setup | Serial port..."
Now the new COM port connects. The original Baud rate and other settings are retained.

I found it out here: https://github.com/TeraTermProject/teraterm/issues/552
where there is also an explanation for the changes that were made.

Regards

Mark


5
µTasker general / Re: Tools that might be of interest to uTasker users
« on: February 09, 2026, 01:14:31 AM »
Hi All

Since I finally moved to Windows 11 and had some issues with COM0COM I'll write up what I found:

1. The present COM0COM version is V3.0.0. This works only is secure boot is disabled in the PC's BIOS; if secure boot is enabled Windows won't start it, which will be seen with a warning in the device manager. If you are happy with disabling secure boot this version is fine (in fact the same as on Win10 as I used thsi version for a few years also with the secure boot disabled).
To disable secure boot in the PC's boot follows: https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/disabling-secure-boot?view=windows-11

2. An older version of COM0COM - V2.2.0 works without disabling secure boot. The following link to that version is here (if it stops working do an Internet search - it should be on sourceforge.net)
https://sourceforge.net/projects/com0com/files/com0com/2.2.2.0/com0com-2.2.2.0-x64-fre-signed.zip/download

Since I don't know of any advantages of 3.0.0 I am going to try to use always 2.2.0 as it avoids the complication (especially for those who are not allowed to disable secure boot on their company PCs).

I found the following useful as I needed to install/uninstall a number of times to do the testing - there is no mention of secure boot issues, but the messages is quite clear "2.2.0 GOOD, 3.0.0 BAD":

https://www.youtube.com/watch?v=5RIcez2Vpdk

Regards

Mark

6
NXPTM M522XX, KINETIS and i.MX RT / Re: Post method
« on: January 23, 2026, 12:29:37 AM »
Hi

Here are few additional tips about handling POST to a web server.

1. Use WireShark to view the POST that is being received to be sure that the type is known. For example if text based content is being received the POST header will contain the content type "text/plain".

2. Ensure that the type is supported by the HTTP server - for example
#define SUPPORT_POST_TEXT
will ensure that it recognises the type and not ignore it.

3. When a recognised/supported POST content type is received the application callback will be called with the event type CAN_POST_BEGIN and the application level can decide whether it wants to accept (return 0) it or ignore it (return 1). Ignored posts will be silently discarded but the transfer is allowed to take place (to nowhere).

4. POST content is either saved to file or passed to the application (on a TCP frame basis).
Posts that are saved to file report success at the end with the callback event INFORM_POST_SUCCESS or INFORM_POST_FAILED.
Posts that are handled by the application layer pass each TCP frame's payload using the event POSTING_DATA_TO_APP and the application uses the content for whatever purpose it chooses - for example it can also save it to a file or interpret its content as it arrives. The final events INFORM_POST_SUCCESS or INFORM_POST_FAILED again signal the end of the complete post content.

5. Plain text post content is usually handled by POSTING_PARTIAL_PARAMETER_DATA_TO_APP and POSTING_PARAMETER_DATA_TO_APP event (POSTING_PARTIAL_PARAMETER_DATA_TO_APP indicates a fragment of a larger plain-text post and POSTING_PARAMETER_DATA_TO_APP indicates either a complete one in a single frame or the last in a larger post. This is typically used for passing parameters (like JSON strings) where the application will parse the content to extract the values (in the case of partial frames it may need to add buffering so that it can collect complete parameters before interpretation is possible).

See fnHandleWeb() in webInterface.c in the uTaskerV1.4 project for some reference handling of the events.

It is recommended to use the simulator to test such transfers, where a break point in fnHandleWeb() allows each event and accompanying data packet to be analysed.

Regards

Mark


7
Hi All

If you ever have a difficulty with COM0CO on Windows 11 this link may come in handy:
https://groups.io/g/win4icomsuite/message/4126

Regards

Mark

8
NXPTM M522XX, KINETIS and i.MX RT / Re: Rookie Question: µTasker "SDKs"
« on: November 20, 2024, 12:15:50 PM »
Hi

It is possible to enable such functionality in the serial loader or the uTasker application but if you load your won application instead of the uTasker application none of its operation is available as only your application is running.

Therefore you can either implement the application using the uTasker project (use the uTasker project as a framework for your own application code) or you need to develop all functionality needed in your own application (as the loaders do not run in parallel with it).

Regards

Mark

9
Hi

When the serial loader has completed its work the application is started and the serial loader is no longer running - therefore its normal that the upload disk is no longer available.

For the disk to re-appear the application would need to implement the same USB-MSD loader functionality, although this is not practically possible as the application would delete itself during the operation.

Typically the application, when it knows that the loader is needed again, will command a reset to the loader and then the serial loader allows the next update.

Alternatively the application allows new code to be saved to an intermediate area in flash and the BM-loader then updates it at the next reset. This would allow USB-MSD to be used (to load to intermediate memory) if the application can implement its own method.

Regards

Mark

10
NXPTM M522XX, KINETIS and i.MX RT / Re: Connecting over Vcom
« on: November 20, 2024, 12:02:52 PM »
Hi

I would try first without RNDIS in case that is causing a problem with its composite configuration.
Also compare the operation withe a reference from https://www.utasker.com/iMX/RT1060.html since these are known to operate correctly.

Regards

Mark

11
USB / Re: USB MSD data corruption MK20DX256VLH7
« on: October 06, 2024, 01:44:40 AM »
Hi

Sorry that I didn't see this post until now.

I don't know why this would happen but it is due to the file object, which is written after loading a new FW, being corrupted. Potentially it was written correctly but later overwritten, causing some values to be modified.

Attached is the latest version of usb_device_loader.c which was modified with this change quite some time ago:
16.01.2017 Check valid file and display for delete if random data    {33}

You will see that it uses
fnCheckFileObject() to verify that the file object is not corrupted and will, if it finds it to be bad, display a file called "UNKNOWN.BIN" with a size matching the application area (instead of trying to display the content according to teh fiel object itself).

This allows the user to do a delete of the file (cleans the application area) and then load the FW (again).

The problem with a corrupted file object can also be that multiple strange files of seemingly random lengths are found and it may otherwise not be possible to delete them to clear it up. This check and the "UNKNOWN-BIN" method ensures easy recovery.

This doesn't help with a source of corruption itself though.

Regards

Mark



12
Hi All

As you are probably aware, the uTasker project typically uses FlexRAM for optimal speed efficiency and divides the FlexRAM into ITC (Instruction Tightly Coupled) for code location and DTC (Data Tightly Coupled) for variables. The FlexRAM partitioning is performed automatically in this mode when the boot loader starts the serial loader or application (when running in RAM).

During intensive testing of SW and watchdog resets it was identified that returning the FlexRAM back to its default configuration was not always guaranteed since this has to be done during the reset command and is not performed automatically in HW during reset. This happened maybe once every 1000 resets or so and is almost certainly due to the fact that the chip's ROM loader - which starts the boot up sequence - fails when OCRAM (general purpose configuration) is disabled during the partitioning (tests where an OCRAM bank was left as it was by default didn't suffer from the issue) and couldn't be returned reliably during the reset operation.

A solution to this, which was tested positively in a long term test of continuous SW and/or watchdog resets, has been added that is recommended to ensure that a board can't remain in an undefined state after a commanded or watchdog reset, noting that it is generally recommended to use an external power-cycling circuit to also capture any potential hanging situation - see https://www.utasker.com/docs/iMX/uTasker_iMX_WDOG.pdf

1. In the bare-minimum (primary) boot loader a routine has been added that can reliably return the FlexRAM settings to their defaults and command reset (the bare-minimum loader operates directly from QSPI flash and can, thus, do this easily.

Code: [Select]
static void fnRestoreFlexRAM(int iReset)
{
    IOMUXC_GPR_GPR16 = IOMUXC_GPR_GPR16_DEFAULT;                         // set the FlexRAM layout back to that taken from the eFuse setting (default configuration)
    if (iReset != 0) {
        APPLICATION_INT_RESET_CTR_REG = (VECTKEY | SYSRESETREQ);         // request cortex core reset, which will cause the software reset bit to be set in the mode controller for recognition after restart
    }
}

2. The location of this routine is added to its Flash configuration, which means that it is - for i.MX RT 10xx parts - at a fixed address of 0x200 offset from the start of QSPI flash:
Code: [Select]
const FLEXSPI_NOR_BOOT_CONFIGURATION __attribute__((section(".boot_hdr.conf"))) __boot_config
= {
    ....
    (unsigned long)fnRestoreFlexRAM                                      // insert the address of a routine that can be called to return the FlexRAM back to default settings and reliably reset the device
};

3. The general SW reset function now uses this call (when it exists) to ensure reliable resets:

Code: [Select]
// This routine is called to reset the processor
//
extern void fnResetBoard(void)
{
#if !defined iMX_BOOTLOADER
    uDisable_Interrupt();
#endif
#if (!defined iMX_BOOTLOADER && !defined NO_STACK_RESET)
    fnStackReset(1);                                                     // {7} if the boot loader supports this method the code will not return
#endif
    APPLICATION_INT_RESET_CTR_REG = (VECTKEY | SYSRESETREQ);             // request cortex core reset, which will cause the software reset bit to be set in the mode controller for recognition after restart
    IOMUXC_GPR_GPR16 = IOMUXC_GPR_GPR16_DEFAULT;                         // set the FlexRAM layout back to that taken from the eFuse setting (default configuration) - although the reset is commanded before executing this line it still operates and avoids the RAM layout being changed when the code is still running
}

and the watchdog interrupt also uses it:

Code: [Select]
// If the watchdog fires this interrupt is called 255 clock cycles before the watchdog reset actually takes place
//
static __interrupt void wdog3_irq(void)
{
    __disable_interrupt();
    #if !defined NO_STACK_RESET
    fnStackReset(0);                                                     // {7} if the boot loader supports this method the code will not return
    #endif
    IOMUXC_GPR_GPR16 = IOMUXC_GPR_GPR16_DEFAULT;                         // set the FlexRAM layout back to that taken from the eFuse setting (default configuration)
    FOREVER_LOOP() {}
}

in both cases as long as the user expressly disables it with
#define NO_STACK_RESET

4. As can be seen from the fnStackReset() code it first checks that the bare-minimum loader does have valid code and so it will use the original technique in case it doesn't.

Code: [Select]
// This routine calls a routine in QSPI flash that reconfigures the FlexRAM back to its default and then conditionally commands a core reset
//
extern void fnStackReset(int iReset)
{
        #if defined SECURITY_OTFAD
    void (*_fnCode)(int) = (void (*)(int))(*(unsigned long *)(FLEXSPI_FLASH_BASE + 0x600)); // fixed location in QSPI flash of code to be executed
        #else
    void (*_fnCode)(int) = (void (*)(int))(*(unsigned long *)(FLEXSPI_FLASH_BASE + 0x200)); // fixed location in QSPI flash of code to be executed
        #endif
    if (((unsigned long)_fnCode < FLEXSPI_FLASH_BASE) || ((unsigned long)_fnCode > (FLEXSPI_FLASH_BASE + 0x8000))) {
        return;                                                          // no valid code exists
    }
    _fnCode(iReset);                                                     // execute (doesn't return but either reset or wdog reset will restart the processor after the flexRAM has been set to default)
}

It is recommended that the bare-minimum loader uses this code (included in recent check-ins) and serial loader and applications the new SW reset and watchdog interrupt code to ensure reset reliability when using code from RAM operation.

Regards

Mark

13
Hi All

Here are a few Q.A.s relevant to building the loader using MCUXpresso, especially when building for the i.MX RT 1064 (which has internal QSPI flash at the address 0x7000 0000 instead of the typical 0x6000 0000, used by external QSPI flash (and also the internal QSPI in the i.MX RT 1024).
Note that the full instructions can be found in the document: https://www.utasker.com/docs/iMX/MCUXpresso.pdf
The details in the document are believed to be complete and accurate and if followed to the letter there should be no issues but deviating based on assumptions that things should be a little different may lead to failure to obtain a bootable image and so modifying details should be avoided to be sure of quick success.

>>The config.h files have the wrong target set - how does it still work for my target, the i.MX RT 1064?
This pre-processor define for the target board is delivered as an environment variable when building with MCUXpresso and the value in the config.h files is not used (it is greyed out by MCUXpresso when viewed in its editor) and is only used when building with methods that cannot be better automated (such as the VS bat file method which uses the values in the headers and so needs them all set to match).
IMPORTANT: when setting the environment variables they must be set for "All configuration" so that the single setting is valid for all. Never change for just one single target configuration!!

>> The properties in the MCUXpresso properties are for the the wrong processor - why does it still work?
The target is not important for building since the compiler is the same for all ARM7s. It is only relevant when debugging so that the debugger presents the correct peripheral registers view (if ever used). It won't harm setting to match the exact chip but is usually not needed.


>>I use a processor with double-precision processor but the project is set for single-precision - why does it still work?

The FPU is probably not used by the loaders (as there is no calculations in the code that need it) and it could be set to single, double or SW to result in the same outcome on most parts (if optimised for the processor's capabilities calculations using FPU may be slightly faster but wouldn't be noticeable).
This is left by default at "single" so that it run on the i.MX RT 1011 as well (which has single precision HW). If it were set to double as default there could be an issue for i.MX RT 1011 users in case the compiler did make use of the FPU and it could result in such users experiencing hard-faults when the code tried to execute if this setting were not explicitly set to single or SW methods.
Since the FPU setting and use is not really relevant it is simpler to just default to single so it can always be used successfully and not cause potential loss of time if were an exception needed by just some.
If the target processor has double precision FPU it can of course be set to that.

>> The uTaskerBoot linker is set to to iMX_RT_1064_FlexSPI_NOR.ld as per the instructions but the loader fails.
The 1064 has one single exception due to its internal memory layout and that is to set this file ONLY to the BM-loader. The serial loaders are linked to run in RAM (so that they can program the Flash) and so ALWAYS (irrespective of the processor) MUST be left as iMX_RT_10XX_FlexSPI_NOR_BOOT.ld. This locates to RAM and doesn't use Flash - therefore its flash setting (0x6000 0000) is not relevant and is left as the one that matches the majority of processors.

The names of the linker scripts reflect their intention
iMX_RT_1064_FlexSPI_NOR.ld <- 1064 means specifically for this part
iMX_RT_1064_FlexSPI_NOR.ld <- NOR means booting/running from NOR flash

iMX_RT_10XX_FlexSPI_NOR_BOOT.ld <- 10xx means suitable for any 10xx part (including 1064)
iMX_RT_10XX_FlexSPI_NOR_BOOT.ld <- BOOT means suitable for operation with the BM-boot loader (i.e. located in RAM)

The BM-loader (primary loader) is configured to use
iMX_RT_10xx_FlexSPI_NOR.ld
by default, which is already suitable for any other i.MX RT 10xx parts and this change is ONLY needed by the i.MX RT 1064.


Regards

Mark



14
Hi

I believe that newer versions of the KEIL compiler have become more GCC compatible and they removed the instrinsic __wifi().

In kinetis.c change

#define __sleep_mode()        __wfi()

to

#define __sleep_mode()        __asm__("wfi")

If this also doesn't work disabled SUPPORT_LOW_POWER in config.h as the instruction is only needed when using the processor's wait mode (to save power when the core has nothing to do).

I see that you are building the target "uTaskerV1.4-BM". This target works together with the uTasker boot loader so it may be easier for you to start with the "uTaskerV1.4" target [you can select the target to be built in the IDE] instead otherwise you will need to build and install the loader before you can test some operation.

Regards

Mark

15
Hi

The fall-back loader is intended mainly as a loader to install new serial loader versions. It can be started from the application using the "fboot" command or from the serial loader using the "fb" command.
If the serial loader were corrupted (check-sum or authentication is invalid) it will behave as if it is not available and start the fall-back loader so that an un-corrupted version can be loaded.
Typically the primary loader is configured to start the fall-back loader if it has counted 16 watchdog resets:
- that means that there is a serial loader (or more likely) an application that is failing (possibly not allowing the serial loader to be commanded)
- after the failure has taken place 16x (if an application had been loaded that almost immediately hard faults due to a certain error were loaded it would watchdog reset every few seconds) the boot loader will start so that the user has the opportunity to load a new serial loader version
- the fall-back loader will typically automatically start the serial loader after 15s, thus giving the user the opportunity to load a new application
- the serial loader typically times out after 60s (when no activity is taking place) and so the cycle will repeat - the idea is that the user should not need to wait that long before the fall-back and then the serial loaders are automatically offered in such a case

Regards

Mark

Pages: [1] 2 3 ... 219