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
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



2
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

3
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



4
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

5
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

6
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.


7
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

8
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





9
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.

10
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

11
 :)

12
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

13
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


14
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

15
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

Pages: [1] 2 3 ... 218