10 years, 6 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 - 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
Be the first to answer this question.