readFlashDataPage in loader

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

readFlashDataPage in loader

Post by RedDave »

There seem to be a number of posts on this subject but none that I've found that seem definitive.

I am attempting to write a flash loader that will boot from either the factory image or the first upgrade, depending on the value in the first word of flash.

I am using an explorerKit and 14.3.3 of xTIMEcomposer.

I have written two applications. Both factory.xe and blue.xe reads the contents of the first word, increments it and writes it back.
factory.xe writes lowest three bits to the coloured LEDs. That the coloured LEDs change on each boot confirms it is working.
blue.xe turns on the single green LED.

loader.xc should read this same value and run factory.xe if even, blue.xe if odd. i.e. it should toggle between the two on each boot. Code for this is below.

It is booting the factory image every time.

The documentation says I should use readFlashDataPage(0). Various forum posts say that this is wrong and I should used readFlashDataPage(BOOT_PARTITON_SIZE). I have tried both, with no success.

There are also posts that say readFlashDataPage() does not work in init(). I have tried it in checkCandidateImageVersion(). No success.

So...
1) What is the definitive answer to what should be passed to readFlashDataPage?
2) Does it work in init()?
3) Is there something else I am doing wrong?
4) How do I debug the flash loader? Is it possible to catch a printf from it? Some other way of debugging?

Code: Select all

#include <platform.h>
#include <xs1.h>
#include <stdio.h>

extern void * unsafe readFlashDataPage(unsigned int address);

enum interest {NOT_INTERESTED, INTERESTED};

static unsigned int selectedAddress;
static int bootCount;

#define BOOT_PARTITON_SIZE  (102400)

// Call first by loader
void init()
{
    printf("LOADER: Init\n");
    selectedAddress = 0;
    unsafe
    {
        bootCount = *(int *)readFlashDataPage(BOOT_PARTITON_SIZE);
    }
}

// Called for each image with correct CRC for first 256 bytes
int checkCandidateImageVersion(int imageVersion)
{
    return (imageVersion == (bootCount % 2)) ? INTERESTED : NOT_INTERESTED;
}

// Called for each image with overall correct CRC, for which INTERESTED was returned
void recordCandidateImage(int imageVersion, unsigned int imageAddress)
{
    selectedAddress = imageAddress;
}

// Called to report which image to boot
unsigned int reportSelectedImage()
{
    return selectedAddress;
}


User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Addendum:

I am programming the flash using the following

Code: Select all

xflash --factory ..\factory\bin\factory.xe --upgrade 1 ..\blue\bin\blue.xe 81920 --loader src\loader.xc --boot-partition-size 102400
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Having failed to find a simple way of debugging the loader I have resorted to bashing data out of digital outputs, then connecting an arduino to read and display the data.

What I have found is strange...

When the loader uses readFlashDataPage to read the data the nybble order in each byte is reversed.

To write (in application)...

Code: Select all

    char scratch[4096];
    int bootCount;

    if (fl_readData(0, sizeof(bootCount), (char*)&bootCount) != 0)
    {
        printf("Failed to read data.\n");
        return -2;
    }
    
    if (bootCount == 0xFFFFFFFF)
        bootCount = 0xABCDEF00;

    bootCount++;
    printf("Boot Count: %d\n", bootCount);

    if (fl_writeData(0, sizeof(bootCount), (char*)&bootCount, scratch) != 0)
    {
        printf("Failed to write data.\n");
        return -2;
    }
To read (in loader)...

Code: Select all

    unsafe
    {
        bootCount = *(int *)readFlashDataPage(BOOT_PARTITON_SIZE);
    }
So, after flashing, the loader reads FFFFFFFF.
The application loads and reads FFFFFFFF and writes ABCDEF01
Press reset.
The loader reads BADCFE10
App writes ABCDEF02
Press reset.
Loader reads BADCFE20.

As you can see the nybble in each byte is reversed.

This makes absolutely no sense to me.
Any ideas as to the cause?
User avatar
CousinItt
Respected Member
Posts: 361
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

I'm not sure I fully understand the loading process, but isn't there a boot rom in the device that loads the code starting at 0 and tries to run it? That's the impression I get from AN00185, for example. Wouldn't that mean that your data flag at address 0 is actually being run as part of the boot program, with unintended consequences? Once again, apologies if I'm getting hold of the wrong end of the stick.
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Yeah, you are missing something.

By default, the flash loader loads the last valid image.

But you can write a custom loader, which is what I am trying to do. Documentation and forum advice differ on the function readFlashDataPage. And I am getting very strange behaviour.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

Add the --verbose flag to the xflash command line to see additional details:

Code: Select all

xflash --verbose --factory ..\factory\bin\factory.xe --upgrade 1 ..\blue\bin\blue.xe 81920 --loader src\loader.xc --boot-partition-size 102400
The reverse nibble storage inside the flash is due to the XMOS devices working in little endianess format:

https://www.xcore.com/viewtopic.php?t=137

https://en.wikipedia.org/wiki/Endianness

From your post, appears that if the LEDs are changing colors, the code is booting correctly along with the reading/writing to the flash? So the issue is the jump to the required flash section?
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Data written to and read from flash using fl_ functionality is correct, evidenced by the LEDs.

The same memory read using readFlashDataPage has nybbles inverted. This is not an Endedness issue. The byte order is correct but the least significant 4 bits and most significant 4 bits in each byte are swapped.
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am

Post by mon2 »

Have you seen the following thread and appnote? Perhaps it will help:

https://www.xcore.com/viewtopic.php?t=4994

Code: Select all

https://www.xcore.com/viewtopic.php?t=4994
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Yes. That's where I started.

I can boot to a choice of images by changing the loader.

The only problem is the fact that the bytes are incorrectly read.

It seems that the "driver" behind readFlashDataPage is different to the fl_ functions.
User avatar
RedDave
Experienced Member
Posts: 77
Joined: Fri Oct 05, 2018 4:26 pm

Post by RedDave »

Yes. That's where I started.

I can boot to a choice of images by changing the loader.

The only problem is the fact that the bytes are incorrectly read.

It seems that the "driver" behind readFlashDataPage is different to the fl_ functions.