This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MCU-PLUS-SDK-AM243X: Custom PRU bootloader

Part Number: MCU-PLUS-SDK-AM243X

Hello,

I followed the example: [FAQ] AM64X: How to Load/Flash PRU binaries into external memory and it works great for application where PRU code doesn't need to change often.

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1183897/faq-am64x-how-to-load-flash-pru-binaries-into-external-memory?tisearch=e2e-sitesearch&keymatch=pru%20AND%20flash#

I have an application where I need to be able to download new PRU programs and store them in the OSPI FLASH, so that I can change PRU program without rebuilding and changing the R5F program.

Here are the steps I'm working on:

1) Using R5F a new PRU binary can be downloaded over UART and then written to an unused area of external OSPI FLASH.

2) During this step the size of the PRU binary can also be written to the FLASH.

3) Then next time AM243x is rebooted or PRU is reloaded a new version of PRU code can be loaded from a dedicated section in external FLASH instead of from an array in the R5F code.

4) To do this the R5F would read the size of the PRU image which was stored in step 2 so it would know the size of the PRU image when reading it from FLASH and writing it to PRU.

Do you see an issues with the steps above, or is there a better way to do this?  

Thanks,

Paul 

  • Hi Paul,

    This seems feasible. Please implement it, let us know if you face any issue

  • I was able to implement this and it is working now, I will spend more time cleaning up this code and add error handling in the future.

    Here is what I'm doing:

    1) RF5 downloads new PRU HEX file over UART port and stores it in an char* array
    2) All the HEX values from the array are parsed out and put into an uint32 array, the first element of the array is the array length
    3) The OSPI FLASH Block at location 0x200000 is erased, (I couldn't get Sector erase to work using TI APIs)
    4) The uint32 array of PRU HEX data is then written to the OSPI FLASH at 0x200000
    4) The array is then read back from the OSPI FLASH and compared to what was written, an error could be thrown if it doesn't match
    5) The pru_init() function was then modified to read the OSPI_FLASH at location 0x200000 to determine length of PRU HEX array
    6) Then entire length of PRU HEX image is read back from OSPI FLASH into an array
    7) PRU then starts to run new code, also if board is rebooted the new PRU code in OSPI FLASH starts running

    Here is main code doing the work:

    char buffer[4096];
    UART_Transaction_init(&trans);
    gNumBytesRead = 0U;
    trans.buf = &buffer[0];
    trans.count = 4096;
    trans.timeout = 4000; //Wait up to 4000 ms
    transferOK = UART_read(gUartHandle[CONFIG_UART_LOG], &trans);

    uint32_t* data=(uint32_t*)gOspiTxBuf;
    uint32_t* data_ver=(uint32_t*)gOspiRxBuf;
    const char* bufferp = buffer;
    uint32_t* hexArray = data;
    size_t bufferSize = strlen(bufferp);
    size_t hexArraySize=1; //First location will be for array size so reserve first location b starting with 1 instead of 0

    // Skip characters until newline since first line in PRU HEX file doesn't have data
    while (*bufferp != '\n') bufferp++;

    //Read all the hexadecimal values from the PRU HEX file and put them into an array of 32bit integers
    while (*bufferp && hexArraySize < bufferSize)
    {
    // Skip non-hexadecimal characters
    while (*bufferp && !isxdigit(*bufferp)) bufferp++;

    if (*bufferp)
    {
    // Convert hexadecimal character(s) to unsigned int
    char* endptr;
    hexArray[hexArraySize] = strtoul(bufferp, &endptr, 16);
    hexArraySize++;
    bufferp = endptr; // Move buffer pointer to the next character
    }
    }
    data[0]=hexArraySize; //Set first element of array to the array length
    ospi_flash_write((uint8_t *) data, hexArraySize*4); //Write the PRU HEX data to the OSPI FLASH 0x200000
    //Read the data back from the OSPI FLASH to validate it is correct
    ospi_flash_read((uint8_t *) data_ver, 4); //Read length of data array
    ospi_flash_read((uint8_t *) data_ver, data_ver[0]*4); //Use length to read entire array
    //Compare original array written to FLASH with array read from FLASH
    for(i=0;i<hexArraySize;i++)
    {
    if(data[i]!=data_ver[i])
    {
    status = SystemP_FAILURE;
    DebugP_logError("OSPI FLASH programming error!\r\n");
    break;
    }
    }
    pru_init(); //Reload PRU with new code in OSPI FLASH

    Change to pru_int() function

    uint32_t data[1024];
    uint32_t size=0;
    ospi_flash_read((uint8_t*) &size, 4); //Read the size of the uint32 array that holds the PRU program, the first location of the array is the length of the array
    ospi_flash_read((uint8_t*) data, size*4); //Now that size is known we can read the entire PRU program array

    status = PRUICSS_writeMemory(gPruIcss0Handle, PRUICSS_IRAM_PRU(PRUICSS_PRUx), 0, data+1, (size-1)*4); //Skip over first element since it is the size of the array