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 ... 218
1
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



2
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

3
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

4
Hi

I don't have experience with using blhost but if the serial loader has been installed into flash I would expect that a reset would cause it to start.

I have, however, worked with the SDP protocol that blhost uses and used the following technique:

1. I build the serial loader using the bat file/make file method which generates and output using (see make_uTaskerSerialBoot_GNU_iMX):

# Create SDP output file and show its size
uTaskerSerialSDP.elf: $(OBJS) $(OBJS2_SDP) iMX_RT_10XX_SDP_BOOT.ld
   $(CC_LNK) $(C_FLAGS) -Os -g -TiMX_RT_10XX_SDP_BOOT.ld -nostartfiles -Xlinker --gc-sections -lm -Wl,-Map=uTaskerSerialSDP_BM.map -o uTaskerSerialSDP.elf $(OBJS) $(OBJS2_SDP)
   $(CC_OBJ) --only-section=.data --only-section=.init --only-section=.text --only-section=.rodata --only-section=.vectors --output-target=binary uTaskerSerialSDP.elf uTaskerSerialSDP.bin
   $(CC_SIZE) uTaskerSerialSDP.elf
   $(CC) -v


This output is suitable for use by loading with the SDP protocol (it is loaded and run in OCRAM)
I think I set this define in config.h
#define CONFIG_SDP_LOADER                                        // build the serial loader to work as a downloaded loader with the NXP serial download protocol

2. The serial loader can be build with any options and the one I use is SREC via USB-CDC

3. When this binary is installed and started (I think it is equivalent to when you load your flashloader and will be suitable for any boards that can run the serial loader since it will be configured with the same flash driver, and can be modified to add more functions such as test functions for production) it runs this serial loader and so appears as a CDC device. Like this the host can load SREC files (in order to install the final serial loader + application into flash) and can be commanded to start with the "go" command.

Regards

Mark

P.S. I use a second i.MX RT for production programming that uses the SDP protocol via USB (as host) connected to fresh i.MX RTs in their ISP mode. It detects when they enumerate, installs the uTaskerSerialSDP.bin that I generated for the target and starts it. The device then enumerates as USB-CDC and the host sends the SREC interface "bc", "ld", SREC image, "go" commands to install the complete serial loader/application.
At the same time the i.MX RT host controls the bed of nails tester to test the board and program other parts on it.
I have used the technique a number of times in quite large volumes - recently I tested/programmed 1000 boards myself and they all programmed without any glitches.


5
The ADC interface 'attempts' to be compatible across processors and ADC types so some of the values will not do anything but can be left so that the interface remains operational with those that need them, or react to them.

The calibration flag should only be set once, the first time the interface is called (for each ADC).

The easiest way to learn the interface is to run the main application in Visual Studio and step through the code so that the effect of flags can be seen. The idea is to start with a basic interface that has a certain amount of features, and basic compatibility although the internal workings may not be highly efficient due to this. One can see which paths are used (and needed) and take these into a custom function if speed is important.

Regards

Mark

6
Hi

The ADC pins are found here: https://www.utasker.com/iMX/iMXRT1060/iMX_RT_1060.xls

To select ADC1_IN9 use
adc_setup.int_adc_controller = iMX_ADC_1;                            // first i.MX RT ADC
adc_setup.int_adc_bit = ADC_SE9_SINGLE;

Optionally pullup/down can also be defined using ADC_INPUT_PULL_DOWN, ADC_INPUT_PULL_UP or ADC_INPUT_PULL_UP_WEAK to the adc_setup.int_adc_mode details.

which causes the configuration (in the ADC driver) with

_CONFIG_PORT_INPUT(1, ADC1_IN9_GPIO_AD_B1_04_GPIO1_IO20, ulPinCharacteristic);


For ADC1_IN10 change adc_setup.int_adc_bit to ADC_SE10_SINGLE.


Presently your code is configuring but not converting (default is to use a conversion interrupt, which you have disabled).
Add ADC_GET_RESULT so that it will do a blocking conversion and return the value.
Note that samples.ucADC_status will then contain ADC_RESULT_VALID, indicating that the result is valid (presently you will find that it is not the case).

Note that I haven't a great many features in the present ADC driver version for the i.MX RT and so HW trigger modes and chaining are not integrated. If you tell me which STK reference contains the method that you would like to use I can add that to the interface.
The HW triggering levels do work well since I have used these successfully in some products.

Regards

Mark





7
NXPTM M522XX, KINETIS and i.MX RT / Re: Caching of (XiP) Flash?
« on: March 14, 2024, 12:03:47 AM »
Note also that using the fnGetParsFile() method to read to a buffer also bypasses any caching. Only the XiP (memory mapped) accesses can be cached.

8
NXPTM M522XX, KINETIS and i.MX RT / Re: Caching of (XiP) Flash?
« on: March 13, 2024, 02:12:07 AM »
The FlexSpi has a cache.

Try
        FLEX_SPI_AHBCR = FLEX_SPI_AHBCR_READADDROPT;                     // disable FlexSPI caching

since that worked for me when I had a similar issue.
It completely disables it but, seeing as the serial loader is running in RAM, there will be no performance disadvantage just turning it off.

Regards

Mark

9
 :)

10
John

I think I have found a simple way to command disconnecting the USB device (and, if required, reconnecting it again.

USBHS0_USBCMD ^= USBHS_USBCMD_RS;

When USBHS_USBCMD_RS is set to 0 (stop mode) it removes its D+ pull-up and so is no longer detected by the host.
When it is set again it reconnects the D+ pull-up and goes to run mode again (and the host detects it and re-enumerates it).

I added this interface so that the registers don't need to be accessed directly (portable):

    fnConfigUSB(USB_DEVICE_REF, 0); // when the parameter is 0 it toggles the RUN mode in order to disconnect/reconnect

but it may not be the best method, so experimental at the moment.
You may be able to prove the suitability for your need by directly controlling it in the register.

Regards

Mark

11
NXPTM M522XX, KINETIS and i.MX RT / Re: un-enumerate USB Device loader?
« on: February 28, 2024, 05:46:15 PM »
Hi

I understand that your serial loader is the device: After uploading a new file the loader will usually perform a SW reset in order to continue and this also causes the device to be disconnected.

As far as I can tell there is no de-installation method that disconnects a device itself but looking at the low level de-installation after a USB reset (in the HW USB interrupt _usb_hs_otg_isr_common()):

        if ((ulInterrupts & USBHS_USBINTR_URE) != 0) {                   // handle USB reset interrupt
            fnDeInitEndpoints(ptrHSUSB, Channel);                        // abort any active endpoints and free transfer buffers
            ptrHSUSB->EPCR0 = (USBHS_EPCR_RXE | USBHS_EPCR_RXR | USBHS_EPCR_TXE | USBHS_EPCR_TXR); // reset data toggle (synchronise) on endpoint 0
            ptrHSUSB->EPSETUPSR = ptrHSUSB->EPSETUPSR;                   // clear all setup token semaphores by reading the EPSETUSR register and writing the same value back
            ptrHSUSB->EPCOMPLETE = ptrHSUSB->EPCOMPLETE;                 // clear all the endpoint complete status bits by reading the EPCOMPLETE register and writing the same value back
#if defined _WINDOWS
            ptrHSUSB->EPSETUPSR = 0;
            ptrHSUSB->EPCOMPLETE = 0;
            ptrHSUSB->USBSTS = USBHS_USBSTS_PCI;                         // usually a port change interrupt follows a reset
#endif
            if ((ptrHSUSB->PORTSC1 & USBHS_PORTSC1_PR) == 0) {           // if we are too slow responding the port reset will have completed
                ptrHSUSB->USBCMD &= ~(USBHS_USBCMD_RS);                  // ensure not in run mode
                ptrHSUSB->USBCMD = USBHS_USBCMD_RST;                     // command a hardware reset
                fnUSBHS_init(((ptrHSUSB->PORTSC1 & USBHS_PORTSC1_PFSC) == 0), (QUEUE_LIMIT)Channel, ucHS_EndpointCount[Channel]); // re-initialise the controller
                ucUSBHS_state[Channel] = 0;
            }
            else {
                ucUSBHS_state[Channel] = USBHS_STATE_RESETTING;          // the ulpi is still detecting the reset state
            }
            ptrHSUSB->USBINTR &= ~(USBHS_USBINTR_SLE);                   // disable the suspend interrupt
            ptrHSUSB->PERIODICLISTBASE_DEVICEADDR = 0;                   // reset device address
            uDisable_Interrupt();                                        // ensure interrupts remain blocked when putting messages to queue
                fnUSB_handle_frame(USB_RESET_DETECTED, 0, 0, &hs_usb_hardware[Channel]); // generic handler routine
                hs_usb_hardware[Channel].ucUSBAddress = 0;               // reset the address to revert back to the default state
            uEnable_Interrupt();                                         // re-enable interrupts
        }


I suspect that it may be necessary to either provoke such a reset or else disable the USB (eg via  USB controller reset) and execute the same, or part of this.


Could you describe exactly the goal and also how it would best be tested?

Regards

Mark


12
Hi

Is the problem that the application is not running when the serial loader is build with the newer linker script?
I wouldn't expect the serial loader to change the behavior of the application since it doesn't configure any of the application's variables.

Regards

Mark

13
Hi

I would expect the DCD to do the same as the SDRAM interface initialisation.
The DCD configuration is designed to be readable, eg.
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_00, GPIO_EMC_00_SEMC_DATA00),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_01, GPIO_EMC_01_SEMC_DATA01),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_02, GPIO_EMC_02_SEMC_DATA02),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_03, GPIO_EMC_03_SEMC_DATA03),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04, GPIO_EMC_04_SEMC_DATA04),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05, GPIO_EMC_05_SEMC_DATA05),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06, GPIO_EMC_06_SEMC_DATA06),
                _DCD_WRITE_LONG_WORD(IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07, GPIO_EMC_07_SEMC_DATA07),


so that it can also be compared with the code method, eg.
    _CONFIG_PERIPHERAL(GPIO_EMC_00, SEMC_DATA00, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA00 on GPIO4-00 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_01, SEMC_DATA01, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA01 on GPIO4-01 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_02, SEMC_DATA02, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA02 on GPIO4-02 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_03, SEMC_DATA03, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA03 on GPIO4-03 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_04, SEMC_DATA04, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA04 on GPIO4-04 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_05, SEMC_DATA05, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA05 on GPIO4-05 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_06, SEMC_DATA06, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA06 on GPIO4-06 - alt function 0 (direction input/output)
    _CONFIG_PERIPHERAL(GPIO_EMC_07, SEMC_DATA07, (IOMUXC_SW_PAD_CTL_PAD_HYS | IOMUXC_SW_PAD_CTL_PAD_PKE | IOMUXC_SW_PAD_CTL_PAD_SPEED_MAX | IOMUXC_SW_PAD_CTL_PAD_DSE_7 | IOMUXC_SW_PAD_CTL_PAD_SRE)); // select SEMC_DATA07 on GPIO4-07 - alt function 0 (direction input/output)


remembering that it is the primary loader (uTaskerBoot) that supplies the DCD.

Regards

Mark

14
Hi

How is the incoming data being received?

When running the (stand-alone) boot loader, the original application is first deleted before receiving and so differences can't be checked - the exception is when loading form SD card or memory stick where the new code is first compared with the original.

If you have a application header I assume you are using an XiP image, where it would be a good idea to put an application version at a defined location in this. Otherwise, the header (with project number, application length and CRC) could also be used since changes to the application would (normally) be recognised by a change in its size and/or CRC).

Regards

Mark

15
Hi

If you enable
#define BOOT_LOADER_SUPPORTS_SDRAM                   // enable when the boot loader is to configure SDRAM for subsequent application use (or when application runs in SDRAM)
when building the primary loader the SDRAM can be used by the serial loader or the application without needing to configure there.

The SDRAM is located at 0x80000000 [SDRAM_ADDR] and so the easiest way to store data to is to use a pointer as follows:

Code: [Select]
unsigned char *ptrSDRAM = (unsigned char *)SDRAM_ADDR;
unsigned char ucByte = 0;
unsigned long ulTestCnt = (4 * 1024 * 1024);
while (ulTestCnt--  != 0) {
    *ptrSDRAM++ = ucByte++;
}
which should, as example,  leave a 0x00, 0x01, 0x02... pattern throughout 4Meg of the SDRAM.

Regards

Mark

Pages: [1] 2 3 ... 218