Recent Posts

Pages: [1] 2 3 ... 10
1
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
2
I am reading the test drive document for the Serial Loader: https://www.utasker.com/docs/iMX/uTaskerLoader_TestDrive.pdf

the doc mentions:
"recovery via serial “Fall-back” loader when a faulty application or a faulty serial loader is installed"

But the doc doesn't describe how this actually happens.   How does uTaskerBoot know to start the fallback loader instead of the serial loader if the serial loader is corrupted?

I see the fallback loader start if the serial loader is missing completely, but how would this work if the serial loader is present, but corrupted or needs to be updated?

thanks



3
Thanks for the reply, I am going to continue trying to get my blhost based reset working with my existing flashloader (based on the NXP mcu-boot project).

I will update here if I have any success.

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
I am trying to completely automate my dev cycle, using command line sdphost to load the flashloader, then blhost to write the uTasker Serial Loader.  This is instead of using MCU Boot Utility.

I can get the SerialLoader written to flash without issues, but I would like to then cause blhost to jump to execution of the SerialLoader.

I tried following this approach: https://community.nxp.com/t5/MCUXpresso-Secure-Provisioning/BLHost-Execute-application-from-NOR/td-p/1546972

It does jump, but the SerialLoader doesn't seem to actually execute correctly, so I must be missing something.

Has anyone tried this with the uTasker SerialLoader?

Here are my commands to try and execute the jump from blhost:
Code: [Select]
../secure_provisioning/blhost -t 5242000 -u 0x15A2,0x0073 -- read-memory 0x60001000 8
Inject command 'read-memory'
Successful response to command 'read-memory'

d1 00 20 41 00 20 00 60

(1/1)100% Completed!
Successful generic response to command 'read-memory'
Response status = 0 (0x0) Success.
Response word 1 = 8 (0x8)
Read 8 of 8 bytes.

Application address:  0x60002000
../secure_provisioning/blhost -t 5242000 -u 0x15A2,0x0073 -- read-memory 0x60002000 8
Inject command 'read-memory'
Successful response to command 'read-memory'

00 c0 2b 20 61 33 00 60

(1/1)100% Completed!
Successful generic response to command 'read-memory'
Response status = 0 (0x0) Success.
Response word 1 = 8 (0x8)
Read 8 of 8 bytes.

Stack pointer:  0x202bc000
Reset vector:  0x60003361
../secure_provisioning/blhost -u 0x15A2,0x0073 -- execute 0x60003361 0 0x202bc000
Inject command 'execute'
Successful generic response to command 'execute'
Response status = 0 (0x0) Success.


6
NXPTM M522XX, KINETIS and i.MX RT / Re: Set up for ADC on i.MX RT... not getting it.
« Last post by mark on March 21, 2024, 10:41:59 PM »
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
7
ah, thanks!  That is working now.  I may forgo the chaining for this test, I am just trying to understand the ADC setup.
8
NXPTM M522XX, KINETIS and i.MX RT / Re: Set up for ADC on i.MX RT... not getting it.
« Last post by mark on March 21, 2024, 06:38:03 PM »
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 / Set up for ADC on i.MX RT... not getting it.
« Last post by jackking on March 21, 2024, 05:24:10 PM »
I am trying to do some extra credit in my SerialLoader and have a test routine that reads ADC inputs, but I'm not having much luck.

I see various other posts about the ADC, I have checked ADC_Timers.h for example config as well as the pdf on ADC usage, but I still get no reading.

I have two inputs on the i.MX RT (1062), GPIO_AD_B1_04 and GPIO_AD_B1_05. which have the analog voltage coming in.  Using the NXP MCUXpresso SDK, I am able to set up ADC_ETC and the ADC channels 1 and 2 with chaining to successfully read both inputs after a chained conversion is triggered by a PIT.

Using uTasker, I don't really have a clue where to start...

I don't know how to understand the mapping of the actual pins applies to the ADC_SETUP.  I assume that the int_adc_bit should define this using one of the ADC_SE defines in iMX.h:
Code: [Select]
#define ADC_SE0_SINGLE          0
#define ADC_SE1_SINGLE          1
#define ADC_SE2_SINGLE          2
#define ADC_SE3_SINGLE          3
#define ADC_SE4_SINGLE          4
#define ADC_SE5_SINGLE          5
#define ADC_SE6_SINGLE          6
#define ADC_SE7_SINGLE          7
#define ADC_SE8_SINGLE          8
#define ADC_SE9_SINGLE          9
#define ADC_SE10_SINGLE         10
#define ADC_SE11_SINGLE         11
#define ADC_SE12_SINGLE         12
#define ADC_SE13_SINGLE         13
#define ADC_SE14_SINGLE         14
#define ADC_SE15_SINGLE         15
#define ADC_ETC_SINGLE          16

But it also mentions these should map to inputs 0...31 (?). and I see ADC_ETC as well, but I don't see how to set that up.

I also see some of the examples seem to set the int_handler multiple times before setting the actual interrupt, wouldn't this just overwrite the previous value and have no effect?
For example in the ADC pdf it has:
Code: [Select]
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.pga_gain = PGA_GAIN_OFF; // PGA gain can be specified for certain inputs
adc_setup.int_handler = fnRangeInterrupt; // handling function
adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
adc_setup.int_adc_controller = 1; // ADC controller 1
adc_setup.int_adc_offset = 0; // no offset
adc_setup.int_adc_mode = (ADC_CALIBRATE | ADC_SELECT_INPUTS_A | ADC_CLOCK_BUS_DIV_2 |
ADC_CLOCK_DIVIDE_8 | ADC_SAMPLE_ACTIVATE_LONG | ADC_CONFIGURE_ADC | ADC_REFERENCE_VREF |
ADC_CONFIGURE_CHANNEL | ADC_SINGLE_ENDED | ADC_SINGLE_SHOT_MODE | ADC_12_BIT_MODE |
ADC_SW_TRIGGERED); // calibrate the ADC - single shot with interrupt on completion
adc_setup.int_adc_sample = (ADC_SAMPLE_LONG_PLUS_12 | ADC_SAMPLE_AVERAGING_32);
// additional sampling clocks
adc_setup.int_adc_result = 0; // no result is requested
adc_setup.int_adc_bit = ADC_DM1_SINGLE; // ADC DM1 single-ended
adc_setup.int_adc_bit_b = ADC_DISABLED; // channel B only valid in HW triggered mode
adc_setup.int_adc_int_type = (ADC_LOW_LIMIT_INT);
// interrupt type (trigger only when lower than the defined level)
adc_setup.int_low_level_trigger = (unsigned short)(ADC_VOLT * 1.3);
// the low level trigger threshold represented as input voltage
adc_setup.int_handler = adc_ready_1; // handling function

Which sets the int_handler twice, once to fnRangeInterrupt and then to adc_ready_1 at the end. How is this supposed to work?

Here is the code I have been trying to get working as a test on the iMX:

Code: [Select]
ADC_RESULTS  samples;

void fnADCresult()
{
// get the sample
fnDebugMsg("ADC SAMPLE: ");
fnDebugHex((unsigned short) samples.sADC_value[0], (sizeof(unsigned short) | WITH_LEADIN | WITH_CR_LF));

        // set up for the next sample (after we get this working once)
}

void fnInitializePots(void)
{
fnDebugMsg("INIT ADC\r\n");

    // set the ADC input pins?
    _CONFIG_PORT_INPUT(6, PIN_GPIO_AD_B1_04_GPIO6_IO20, (0));
    _CONFIG_PORT_INPUT(6, PIN_GPIO_AD_B1_05_GPIO6_IO21, (0));

    // now we need to set up the ADC to read the pot values
    ADC_SETUP adc_setup; // interrupt configuration parameters
    adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
    adc_setup.pga_gain = PGA_GAIN_OFF; // PGA gain can be specified for certain inputs
    adc_setup.int_priority = PRIORITY_ADC; // ADC interrupt priority
    adc_setup.int_adc_controller = iMX_ADC_1;                            // first i.MX RT ADC
    adc_setup.int_handler = 0; // handling function, removed for now
    adc_setup.int_adc_bit = ADC_SE10_SINGLE;                              // which pin is this?
    adc_setup.int_adc_offset = 0; // no offset
    adc_setup.int_adc_mode = (ADC_CALIBRATE | ADC_SELECT_INPUTS_A | ADC_CLOCK_BUS_DIV_2 | ADC_CLOCK_DIVIDE_8 | ADC_SAMPLE_ACTIVATE_LONG | ADC_CONFIGURE_ADC | ADC_REFERENCE_VREF | ADC_CONFIGURE_CHANNEL | ADC_SINGLE_ENDED_INPUT | ADC_SINGLE_SHOT_MODE | ADC_12_BIT_MODE | ADC_SW_TRIGGERED); // note that the first configuration should calibrate the ADC - single shot with interrupt on completion {12}
    adc_setup.int_adc_sample = (ADC_SAMPLE_LONG_PLUS_12 | ADC_SAMPLE_AVERAGING_32);
    // additional sampling clocks
    adc_setup.int_adc_result = &samples;
    adc_setup.int_adc_bit_b = ADC_DISABLED; // channel B only valid in HW triggered mode
    adc_setup.int_adc_int_type = (ADC_END_OF_SCAN_INT);


    fnConfigureInterrupt((void *)&adc_setup);                            // configure and start next sequence
    fnADCresult();

}

This results in a value of 0x0000. from the result (which isn't correct).

After/if I get this working, I definitely wouldn't know how to get chaining to work for using both inputs at the same time!

Thanks



10
µTasker general / Re: Method for Serial Loader to track application version?
« Last post by jackking on March 19, 2024, 02:44:39 PM »
I added a version to the boot_header file and then modified the loader to handle it for checking the version number and file validity (since it was looking for 0xff in those bytes).  Now I can quickly check if a new application is a newer version vs. doing a byte for byte compare every time.

Code: [Select]
// We add 760 bytes of padding between the header and the start of code in order to
// align the code on a 1k byte boundary (ensures on-the-fly decryption compatibility,
// library compatibility and also allows interrupt vectors to remain in code)

02f8                   // first two bytes specify the length
0f0000        // specify DTC/ITC and OCR
00010000               // version 00 01 00 00   = version 01.00
ffffffffffffff
ffffffffffffffff

ffffffffffffffff
ffffffffffffffff
ffffffffffffffff
ffffffffffffffff

ffffffffffffffff
ffffffffffffffff
ffffffffffffffff
ffffffffffffffff
Pages: [1] 2 3 ... 10