5 years, 5 months ago.

Dealing with echos using Serial

I'm trying to write a routine that will flash an LPC812 from a KL25Z using the serial bootloader, but I'm running into issues with echos. Basically, as soon as the LPC812 says Synchronized<CR><LF>, it starts to echo everything it receives. So when I reply with Synchronized<CR><LF> and do a scanf() to get the OK<CR><LF> response, instead I get ed<CR><LF>, the last two echoed characters from Synchronized<CR><LF> that were probably still in the FIFO. Is there another function I should be using besides scanf()?

UPDATE: Here's some working code as per Erik's request. printNoEcho() does dummy reads to eliminate the echoed characters until I can tell the bootloader to disable them:

main.cpp

#include "mbed.h"
#include "CRC.h"
#include "Firmware.h"

Serial pc(USBTX, USBRX);
Serial target(PTD3, PTD2);
DigitalOut reset(PTE0);
DigitalOut isp(PTE1);

void printNoEcho(const char* str)
{
    int i = 0;

    while (str[i] != '\0') {
        target.putc(str[i++]);
        target.getc();
    }
}

int updateFirmware()
{
    char respStr[32];
    int returnCode;

    //Reset the target
    reset = 0;
    isp = 0;
    wait_us(100);
    reset = 1;
    wait_us(10000);

    //Synchronize the baud rates
    target.putc('?');
    target.scanf("%s", respStr);
    if (strcmp(respStr, "Synchronized") != 0)
        return -5;
    printNoEcho("Synchronized\r\n");
    target.scanf("%s", respStr);
    if (strcmp(respStr, "OK") != 0)
        return -4;

    //Send the crystal frequency
    printNoEcho("12000\r\n");
    target.scanf("%s", respStr);
    if (strcmp(respStr, "OK") != 0)
        return -3;

    //Turn off echo
    printNoEcho("A 0\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;

    //Verify the part ID
    target.printf("J\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;
    int partID;
    target.scanf("%i", &partID);
    if (partID != 0x00008122)
        return -2;

    //Unlock the flash programming commands
    target.printf("U 23130\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;

    //Prepare all sectors for erasure
    target.printf("P 0 15\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;

    //Erase all of the sectors
    target.printf("E 0 15\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;

    //Send the new firmware image one sector at a time
    for (int sector = 0; sector < 16; sector++) {
        //Prepare to copy the new sector to RAM
        target.printf("W 268436224 1024\r\n");
        target.scanf("%i", &returnCode);
        if (returnCode != 0)
            return returnCode;

        //Copy the new sector to RAM
        for (int i = 0; i < 1024; i++) {
            target.putc(g_FirmwareImage[(sector * 1024) + i]);
        }

        //Prepare the sector for writing
        target.printf("P %i %i\r\n", sector, sector);
        target.scanf("%i", &returnCode);
        if (returnCode != 0)
            return returnCode;

        //Copy the new sector in RAM to flash
        target.printf("C %i 268436224 1024\r\n", sector * 1024);
        target.scanf("%i", &returnCode);
        if (returnCode != 0)
            return returnCode;
    }

    //Verify the checksum
    target.printf("S 0 16384\r\n");
    target.scanf("%i", &returnCode);
    if (returnCode != 0)
        return returnCode;
    unsigned int devCrc;
    target.scanf("%u", &devCrc);
    if (devCrc != CRC32(g_FirmwareImage, 16384))
        return -1;

    //Reset the target again
    reset = 0;
    isp = 1;
    wait_us(100);
    reset = 1;

    //No errors!
    return 0;
}

int main()
{
    //Configure the target serial port
    target.baud(230400);

    //Perform the firmware update
    pc.printf("Performing firmware update...");
    int ret = updateFirmware();
    if (ret == 0)
        pc.printf("success!\n");
    else
        pc.printf("failed! (return code: %i)\n", ret);

    //Don't exit main!
    while(1);
}

The KL25s FIFO is 4 long iirc, so that makes sense. But what doesn't make sense is what you see. There is no reason I can see why it wouldn't leave the fifo, you must read the values to get them, when that happens they leave the fifo. As far as I am aware you cannot read from FIFO without removing the characters from it. Is this still fairly simple code for this part? If yes, can you post it?

posted by Erik Olieman 08 May 2014

It makes sense because the LPC812 is echoing back Synchronized<CR><LF>. So when I do a scanf(), that's what is in the FIFO, the last 4 chars that echoed back. The LPC812 probably hasn't had a chance to overwrite them yet. I've attached my code to the original question for readability. It works now, but I had to write my own printing function that discards the echos with useless getc()'s.

posted by Neil Thiessen 08 May 2014
Comment on this question
Be the first to answer this question.

You need to log in to post a question