Shop OBEX P1 Docs P2 Docs Learn Events
P1 loader for the P2 — Parallax Forums

P1 loader for the P2

Here is a program that will load a program onto the P1 from the P2.

#define __P2__ 1

#include <stdio.h>
#include <propeller.h>
#include "smartpins.h"


int Verify(void);
void DoReceive(void *);
void SendHandShake(void);
void SendLong(int);
void Reset(void);
void Flush(void);


#define LOW 40
#define HIGH 20
#define PGMTX 20
#define PGMRX 21
#define RESET 22


unsigned int TxHand[] =
{0b01011100111101011111000111001010,
 0b00111100001001001011110010001000,
 0b11011011100010110011001011011001,
 0b00111010101011101101011010011111,
 0b11100110111101110100000001010110,
 0b00110011100000011111010010101001,
 0b00000100001110111111011000011000,
 0b10011000001101000101001101010000};

unsigned int Image[] = 
{0x4C4B400,0x10B66F,0xAF80AF0,0xAFC0018,0x20008,0x80000008,0x10C7893F,0x322C06A4,
0xA0BC21F0,0xABCF4BB,0x5C540007,0xDFCF404,0x68FCF500,0x83CF4BB,0x5C7C0012,0x8BC2210,
0x80FC2004,0x8BC0010,0x80FC2004,0x8BFC810,0x80FC2004,0x5C7C0012,0x0,0xACC,
0x0,0x7B4,0x8BC2811,0x80FC2204,0x0,0x8BC2E11,0x80FC2204,0x0,
0x8BC3411,0x80FC2204,0x0,0x8BC3A11,0x80FC2204,0x0,0x8BC4011,0x80FC2204,
0x0,0x8BC4611,0x80FC2204,0x0,0x8BC4C11,0x80FC2204,0x0,0x8BC5211,
0x80FC2204,0x0,0x5C7C0012,0x8BC0011,0x80FC2204,0x5C7C0012,0x8BC0211,0x80FC2204,
0x5C7C0012,0x8BC0411,0x80FC2204,0x5C7C0012,0x8BC0611,0x80FC2204,0x5C7C0012,0x8BC0811,
0x80FC2204,0x5C7C0012,0x8BC0A11,0x80FC2204,0x5C7C0012,0x8BC0C11,0x80FC2204,0x5C7C0012,
0x8BC0E11,0x80FC2204,0x5C7C0012,0x8BC1011,0x80FC2204,0x5C7C0012,0x8BC1211,0x80FC2204,
0x5C7C0012,0x8BC1411,0x80FC2204,0x5C7C0012,0x8BC1611,0x80FC2204,0x5C7C0012,0x8BC1811,
0x80FC2204,0x5C7C0012,0x8BC1A11,0x80FC2204,0x5C7C0012,0x8BC1C11,0x80FC2204,0x5C7C0012,
0x8BC1E11,0x80FC2204,0x5C7C0012,0x8BCF411,0x80FC2204,0xA0BC1E11,0xA0BC227A,0x5C7C0012,
0x8BC2211,0x5C7C0012,0xA0BD207A,0x60FD200F,0x54BCCE90,0x28FCF404,0x84FC2004,0x83C0010,
0x80BCCE6B,0xE4FCF466,0x5C7C0000,0x200,0x5CFCEE6F,0xA0BC220F,0x5C7C0000,0xA0BD207A,
0x60FD200F,0x54BCE690,0x28FCF404,0x8BC0010,0x80FC2004,0x84BCE66B,0xE4FCF473,0x5C7C0000,
0xFFFF,0xFFFFFFFF,0x0,0xFF00FF,0xF0F0F0F,0x33333333,0x55555555,0x3CFC0000,
0xA4BCF400,0x62BCF400,0xA0FC0000,0xA0E80001,0x623CF478,0x80E80010,0x623CF47B,0x80E80008,
0x623CF47C,0x80E80004,0x623CF47D,0x80E80002,0x623CF47E,0x80E80001,0x5C7C0000,0x0,
0x0,0xA0BD1E00,0x5CFD1C7F,0xA4BD2000,0xA2BC0001,0x5C6800AF,0x5CFD1C7F,0x80BD2000,
0xA0FC0000,0xC37D2000,0x5C7000A1,0x2CBC0290,0x80FD2001,0xE3BD1E01,0xC8BC0000,0x28FC0201,
0xE4FD209D,0xA0BC028F,0x5C7C0000,0x0,0xA0BD4600,0x6CBD4601,0xA9BC0000,0x70FD4601,
0xA8BC0201,0x5CFD4491,0xC37D4600,0xA4B00000,0x627D4601,0xA4940201,0x5C7C0000,0xA4FC0001,
0xA0FC0200,0x5C7C00A2,0xA0BCF400,0x48BCF401,0x4CBC0200,0xA0FC0000,0x2BFC0201,0x80B0007A,
0x80BCF47A,0x5C5400B6,0x5C7C0000,0xAE0,0xBD20BB,0xA0BCF400,0xD7D2006,0x5C7000BE,
0x8BC0002,0x863C0001,0x828F402,0xC7D2007,0x5C7C0000,0x0,0x800,0x0,
0x8BCF411,0x80FC2204,0xA0BD2011,0x863D8A11,0x80BC227A,0x5C6800E2,0xA0BD8A90,0x54FDAAE4,
0x54FDB0E5,0x54FDB6E6,0x54FDBCE7,0x80FCF40F,0x28FCF404,0x8BC0090,0x80FD2004,0x80BDAAC6,
0x8BC0090,0x80FD2004,0x80BDB0C6,0x8BC0090,0x80FD2004,0x80BDB6C6,0x8BC0090,0x80FD2004,
0x80BDBCC6,0xE4FCF4D5,0x5CFD8EE4,0x5C7C0012,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0xAF4,0x5C7C005B,0x7FC,0x5C7C002E,
0xAE8,0xA0BC0601,0xA0FC0000,0x8BC0403,0x80FC0604,0x867C0400,0x80D40001,0x84D42214,
0x5C7C0031,0xAE8,0xA0FC1C00,0x5C7C005B,0x86C,0x5C7C005B,0xAA0,0x84FC2004,
0x83C1E10,0x84FC2004,0x83C1C10,0xA0BC1C10,0x5C7C002B,0xAF0,0x5C7C0031,0xBB4,
0x84BC0400,0xA0FC0200,0x5C7C005B,0xA04,0x5C7C0043,0xAE4,0x8BC0008,0xC37C0000,
0x80E82210,0xA0BCF400,0x5C7C005D,0x80FC1004,0x84FC221C,0xA0BC200E,0x8BC1C10,0x80FC2004,
0x8BC1E10,0x80FC2004,0xA0BC220F,0xA0FCF42E,0x5CFCD462,0xA0FC0000,0xA0FC1C00,0x5C7C005B,
0x8E8,0xA0FC0001,0x5C7C005B,0x8E8,0x5C7C002B,0x3E8,0x80FC1C01,0x5C7C005B,
0x930,0x627C1C01,0xA0FC0000,0x80E8220C,0x5C7C005B,0x90C,0x80FC2208,0x5C7C005B,
0x8E8,0x627C1C02,0xA0FC0001,0x80E8220C,0x5C7C005B,0x90C,0x84FC224C,0x5C7C005B,
0x8E8,0x84FC2258,0xA0FC0E01,0xA0BC0DF4,0x2CBC0E00,0x68BC0C07,0xA0BFE806,0xA0BC0DF6,
0x68BC0C07,0xA0BFEC06,0xA0BC220F,0xA0FC0E01,0xA0BC0DF4,0x2CBC0E00,0x64BC0C07,0xA0BFE806,
0xA0BC0DF6,0x68BC0C07,0xA0BFEC06,0xA0BC220F,0xA0BC0FF1,0x5C7C003D,0xBAC,0x5C7C00C8,
0x24,0x5C7C00EA,0x8BC0A06,0x80BC0E05,0xA0BC0A07,0xF8FC0A00,0x84FC0001,0xC37C0000,
0x5C5400E5,0x5C3C00C7,0xA0BC220F,0x5C7C0040,0x0,0x5C7C002E,0x3E8,0x5C7C003A,
0xBB0,0x8BC0C07,0xA0BC0006,0x5CFD4491,0xA0BC0E00,0x5C7C002E,0xF4240,0x83C0005,
0xA0BC0006,0x5C7C003D,0xBA0,0x5CFD4491,0x83C0006,0x5C7C003D,0xBA4,0xA0FC02FA,
0x83C0E06,0x5C7C003D,0xB9C,0x83C0006,0x5C7C003D,0xB98,0x83C0006,0xA0BC0007,
0x5C7C003D,0xBAC,0x83C0E06,0x5C7C0040,0xBA8,0x5CFD74B2,0x83C0007,0xA0BC220F,
0xA0BC220F,0x877C0405,0x80F02274,0x627C0003,0x80D4226C,0x60FC02FF,0xA0BC0E01,0xA0BC0C01,
0x2CFC0C10,0x2CFC0E18,0x68BC0E06,0xA0BC0C01,0x2CFC0C08,0x68BC0E01,0x68BC0E06,0xA0BC0A00,
0xA0BC0C02,0x5C7C00C8,0x18,0x84FC0C04,0x877C0C03,0x83C0E05,0x80FC0A04,0x5C4400E4,
0x5C3C00C7,0xA0BC0E02,0x84FC0E04,0x64FC0E03,0x80FC0E04,0x60FC0403,0x80BC0E00,0x80FC2214,
0xA0BC0E00,0x80FC220C,0x3C0207,0x84FC0401,0x80FC0E01,0xC37C0400,0x84D42214,0xA0BC220F,
0xA0BC1800,0x5C7C0043,0xAEC,0x8BC0008,0xC37C0000,0x80E82210,0xA0BCF400,0x5C7C005D,
0x80FC1004,0x84FC221C,0xA0BC000C,0x5C7C005B,0xAD8,0xF07CF200,0xA0BC220F,0xA00,
0x0,0x96C,0x0,0x0};

unsigned int RxData[20];
char Buffer[1024];
int Stack[50];
volatile int T;
volatile int B;
volatile int Clear;

int main(int argc, char** argv)
{
    int i;

    printf("Starting\n");

    printf("Size: %d\n", sizeof(Image));

    _pinh(PGMTX);
    _pinh(RESET);
    memset(Buffer, 0, sizeof(Buffer));

    cogstart(DoReceive, NULL, Stack, 50);

    _waitms(2000);

    printf("Reset\n");

    Reset();

    printf("Calibration\n");
    Calibrate();

    printf("HandShake\n");

    SendHandShake();

    i = Verify();
    if (i != 0)
    {
        printf("Verify Failed\n");
        return -1;
    }

    _waitms(100);

    printf("Loading\n");

    // Send command 0 - shutdown 1 - load 2 - program 3 - program run
    SendLong(1);

    // Send Program size
    SendLong(sizeof(Image)/4);

    Flush();

    // note code have sent image 1 byte at a time
    for (i=0;i<sizeof(Image)/4;i++)
    {
        if (B != 0)
        {
            printf("Bits: %d\n", B);
            printf("RxData: %x\n", RxData[0]);
            printf("Image: %d\n", i);
            return -2;
        }
        SendLong(Image[i]);
    }

    // Get Load Response
    for (i=0;i<1000;i++)
    {
        Calibrate();
        if (B != 0)
            break;
        _waitus(100);
    }

    printf("Data(%d): %32b\n", B, RxData[0]);

    if (RxData[0] == 0x00)
    {
        printf("Program Loaded\n");
    }

    printf("Done\n");

    while (1)
    {
        _waitms(1000);
    }
}

void SendHandShake()
{
    int i, j;
    int n;
    unsigned int Data;

    n = 32;

    for (j=0;j<8;j++)
    {
        Data = TxHand[j];

        if (j==7)
            n = 26;

        for (i=0;i<n;i++)
        {
            _pinl(PGMTX);
            if ((Data & 0x80000000) != 0)
                _waitus(HIGH);
            else
                _waitus(LOW);

            _pinh(PGMTX);
            _waitus(LOW+HIGH);
            Data = Data << 1;
        }
    }
}

void SendLong(unsigned int tx)
{
    int i;

    for (i=0;i<32;i++)
    {
        _pinl(PGMTX);
        if ((tx & 0x01) != 0)
            _waitus(HIGH);
        else
            _waitus(LOW);

        _pinh(PGMTX);
        _waitus(LOW+HIGH);
        tx = tx >> 1;
    }
}

void Reset()
{
    _pinl(RESET);
    _waitms(500);
    _pinh(RESET);
    _waitms(90);
}

/*
 * @brief Send 1 0 calibration
 */
void Calibrate()
{
    _pinl(PGMTX);
    _waitus(HIGH);
    _pinh(PGMTX);
    _waitus(LOW+HIGH);
    _pinl(PGMTX);
    _waitus(LOW);
    _pinh(PGMTX);
    _waitus(LOW+HIGH);
}

int Verify()
{
    int i;
    unsigned int v;
    int s;

    Flush();

    // get response
    for (i=0;i<250;i++)
    {
        Calibrate();
        _waitus(LOW+HIGH);
    }

    _waitms(80);

    // shift 5 bits over
    for (i=0;i<8;i++)
    {
        v = RxData[i] << 5;
        v = v | (RxData[i+1] & 0xfc000000) >> 27;
        if (i == 7)
            v = v | 0x350;
        if (v != TxHand[i])
            return -1;
    }

    Flush();

    // get version
    for (i=0;i<8;i++)
    {
        Calibrate();
        _waitus(LOW+HIGH);
    }

    _waitms(10);

    if (RxData[0] != 0x80000000)
        return -1;

    return 0;
}

void DoReceive(void *par)
{
    unsigned int i = 0;
    int t;
    int v;
    int f;

    _pinstart(PGMRX, P_INVERT_A | P_HIGH_TICKS, 0, 0);

    f = _clkfreq / 1000000;

    Clear = 1;

    while (1)
    {
        while (_pinr(PGMRX) == 0)
            _waitus(5);

        if (Clear != 0)
        {
            B = 0;
            T = 0;
            RxData[0] = 0;
            i = 1 << 31;
            Clear = 0;
        }

        B++;
        t = _rdpin(PGMRX) / f;
        if (t < LOW-5)
            RxData[T] = RxData[T] | i;

        i = i >> 1;
        if (i == 0)
        {
            RxData[++T] = 0;
            T = T & 1023;
            i = 1 << 31;
        }
    }

}

void Flush()
{
    Clear = 1;
    B = 0;
}

This took several days of work to get to this end result. Like any good puzzle there where a lot of pieces and some of them were missing.
I first started out reverse engineering the Proploader program using Visual Studio in C++. This program has many functions and includes code to program the P2. I needed to follow the code to just send a program to the P1.
The code seemed convoluted to say the least, but I push on.
I then decided to look for the P1 bootloader manual and found this to be nonexistent. I then checked the forum and luckily found the boot loader manual from Chip. This explained a lot of the chaos.
The P1 bootloader was looking for binary data and not serial data. The Proploader program had to make serial data look like binary data. The crazy data being sent by the Proploader was actually binary data.
Now I had a manual that explained each step needed to program the P1.
I continue to write the program in C++ in Visual Studio so that I could get each step of the process to work and was able to use break points to see what was going in each of the steps. Like any good puzzle you need to see if the pieces fit.
After getting the Visual Studio program to load a program onto the P1 I moved to the P2. Now the P2 can just use binary data and didn't need to use serial at all. This meant starting over with different code structure since I could just program directly with no special characters.

Now for you new people, there is no P1 without serial attached to it. The P1 mini is no more. So, the only way you can make this work is to use the bread board version.
Using Visual Studio Code now I started writing the binary version of the loader. Sending binary data was simple enough and only required special timing to do the 1 and zeros. Getting the data back from the P1 not so simple. I decided to use a smart pin instruction that would give me the binary value returned from the P1.
Now it was just a matter of putting all the pieces together and getting the timing to work.
I now know why the Proploader program is so complicated and programming the P2 is so simple.

Where am I going with this. The next stop is to move the program onto the ESP32.

Mike

Sign In or Register to comment.