Skip to main content
carlogulliani
Associate III
December 7, 2015
Question

uart + xmodem1k. Get incorrect char in the beginning of data

  • December 7, 2015
  • 12 replies
  • 1863 views
Posted on December 07, 2015 at 18:07

The original post was too long to process during our migration. Please click on the attachment to read the original post.
    This topic has been closed for replies.

    12 replies

    Tesla DeLorean
    Guru
    December 7, 2015
    Posted on December 07, 2015 at 19:39

    Do you have an adequate stack to accommodate this data?

    Is f_puts() appropriate? It's NOT a string, and you're NOT terminating it. Use f_write() and write the block of bytes in place.

    With these protocols you are going to have to own the synchronization/resych tasks, you can't assume everything is going to work perfectly.

    Looks to be sending the SAME block again. Have you tried different Terminal programs to see if it's the specific one you are using that's stuffing the extra NUL

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    carlogulliani
    Associate III
    December 7, 2015
    Posted on December 07, 2015 at 20:21

    Yes, I have stack to store received data. I'm not sure it is an extra NUL, it's the last char of sending data.

    Here is the code for transmitting

    byte

    [] bb =

    new
    byte

    [1030];
    bb[0] = STX;
    bb[1] = blocknumber;
    bb[2] = (

    byte

    )(255 - blocknumber);
    for

    (

    byte

    b: sector)
    {
    bb[3+k] = b;
    }
    bb[SECSIZE+3] = (

    byte

    )(crc16 >> 8);
    bb[SECSIZE+4] = (

    byte

    )(crc16 & 0xff);
    bb[SECSIZE+5] = 0x00; // this char moves to the 0 position of buffer, if I change it to 0x1A or something else, I see new value...
    putChar(bb,

    ''Block ''

    +blocknumber);

    And if I have a wrong data, sum sends NAK and my transmitting program sends this block again. But there is no good result, because I send the same block 10 times while I get ACK I used f_puts just to try to write something to file
    Tesla DeLorean
    Guru
    December 7, 2015
    Posted on December 07, 2015 at 21:38

    This is not part of the protocol
     bb[SECSIZE+5] = 0x00;

    You are supposed to be sending 1024+5 (1029) bytes, not as a string
    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    carlogulliani
    Associate III
    December 7, 2015
    Posted on December 07, 2015 at 22:13

    The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6dL&d=%2Fa%2F0X0000000bs9%2FuaoDQYYP7Hl5wVmbPjS7CKPgd57YdZ9_rWbBvriZS1M&asPdf=false
    carlogulliani
    Associate III
    December 7, 2015
    Posted on December 07, 2015 at 22:22

    And here is my sender

    public
    boolean send(String tfile) throws IOException
    {
    fileName = tfile;
    char
    errorcount;
    byte
    blocknumber, character;
    byte
    [] sector = 
    new
    byte
    [SECSIZE];
    int
    nbytes;
    DataInputStream dis;
    File f = 
    new
    File(tfile);
    dis = 
    new
    DataInputStream(
    new
    FileInputStream(tfile));
    errStream.println(
    ''file open, ready to send''
    );
    System.
    out
    .println(
    ''file open, ready to send''
    );
    errorcount = 0;
    blocknumber = 0x01;
    int
    count = 0;
    gotChar = 
    false
    ;
    do
    {
    character = getChar();
    System.
    out
    .println(
    ''Initial character, obtained: ''
    + (
    int
    )character);
    if
    (character == NAK || character == CRC) 
    break
    ;
    gotChar = 
    true
    ;
    if
    (character != NAK || character != 
    'C'
    )
    {
    ++errorcount;
    }
    } 
    while
    (character != NAK || character != 
    'C'
    );
    System.
    out
    .println(
    ''Start Transmitting''
    );
    while
    ((nbytes = dis.read(sector))!=0)
    {
    int
    p = (
    int
    )(count*SECSIZE*100/f.length());
    _progressBar.setValue(p);
    count++;
    if
    (nbytes <= -1)
    {
    break
    ;
    }
    if
    (nbytes < SECSIZE)
    {
    sector[nbytes]=CTRLZ;
    }
    errorcount = 0;
    while
    (errorcount < MAXERRORS)
    {
    errStream.println(
    ''{''
    + blocknumber + 
    ''}''
    );
    System.
    out
    .println(
    ''{''
    + (
    int
    )blocknumber + 
    ''}''
    );
    char
    crc16 = crc16(sector);
    byte
    [] bb = 
    new
    byte
    [SECSIZE+6];
    bb[0] = (SECSIZE == 128) ? SOH : STX;
    bb[1] = blocknumber;
    bb[2] = (
    byte
    )(255 - blocknumber);
    for
    (
    byte
    b: sector)
    {
    bb[3+k] = b;
    }
    bb[SECSIZE+3] = (
    byte
    )(crc16 >> 8);
    bb[SECSIZE+4] = (
    byte
    )(crc16 & 0xff);
    //bb[SECSIZE+5] = 0x00;
    putChar(bb, 
    ''Block ''
    +blocknumber);
    if
    (getChar() != ACK)
    {
    ++errorcount;
    }
    else
    break
    ;
    }
    blocknumber = (
    byte
    )((++blocknumber) % 256);
    }
    boolean isAck = 
    false
    ;
    while
    (!isAck)
    {
    putChar(EOT, 
    ''EOT''
    );
    isAck = getChar() == ACK;
    }
    errStream.println(
    ''Transmission complete.''
    );
    return
    true
    ;
    }
    protected
    byte
    getChar() throws IOException
    {
    byte
    something = (
    byte
    )inStream.read();
    return
    something;
    }
    protected
    void
    putChar(
    byte
    [] b, String debug) throws IOException
    {
    System.
    out
    .println(debug + 
    '', ''
    + b.length);
    byte
    [] b2 = 
    new
    byte
    [b.length+1];
    int
    i = 0;
    for
    (
    byte
    b1 : b)
    {
    b2[i++] = b1;
    System.
    out
    .print((b1 & 0xFF)+
    '' ''
    ); 
    // showing all my buffer by byte
    }
    System.
    out
    .println(
    ''''
    );
    System.
    out
    .println(i);
    outStream.write(b); 
    }
    protected
    char
    crc16(
    byte
    [] bytes)
    {
    char
    crc = 0x0000;
    for
    (
    byte
    b: bytes)
    {
    crc = (
    char
    ) ((crc << 8) ^ crctable[((crc >> 8) ^ b) & 0x00ff]);
    }
    return
    (
    char
    ) (crc);
    }

    Tesla DeLorean
    Guru
    December 7, 2015
    Posted on December 07, 2015 at 23:45

    Ok

    #define MAXCLISTRING SIZE+5 // NOT SIZE+6

                if (checkCRC16(&rxString[3], SIZE) == 1)

                {

                    led_toggle(GPIO_PIN_15);

                    xbuf[0] = ACK;

     

                    UINT* bw;

                    f_write(&fil, &rxString[3], SIZE, (UINT*)&bw); // write in-place

                    if (bw > 0) led_toggle(ORANGE);

                }

    Your receiver doesn't need to clear the buffer, only reset the index. However you probably want it to attempt to resync if the first character in the buffer is wrong, rather than keep filling it with 1000+ bytes that will be thrown away.

    Your sender needs to wait for the response, don't let it time out.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    carlogulliani
    Associate III
    December 8, 2015
    Posted on December 08, 2015 at 11:25

    I found that I receive mixed bytes, I can see the order which was sent and I see mixed bytes in my buffer. My sender waits response and there is not problem.

    I commented part of code and use just receiver of data (also I send only data without headers and CRC). I send an image and I got the image, which has the same count of Kb which I sent, but when I open this image I see that the picture's pixels moved in different position then original pic.

    How can I control the order of received bytes, maybe I have to set some setting for usart or dma handler?

    dthedens
    Visitor II
    December 8, 2015
    Posted on December 08, 2015 at 21:53

    Perhaps it is an endian issue.  RGB on an ARM might not be RGB on an Intel PC

    carlogulliani
    Associate III
    December 8, 2015
    Posted on December 08, 2015 at 23:31

    No sure. I tried other formats, not only images... The same problem.

    I made a test, I have an error counter in my sender code, when I'm sending NAK from stm32, I'm increasing this counter and when it has 10 I increase block number. So, now I increased the limit of this counter, also I put breakpoint on my stm32, where I compare current index and buffer size, so I have a button, which sends NAK, when I check break point every 4th data is correct.

    In the other words, I check break point and see wrong bytes order, I press resume, the next data which comes is correct, I pressed resume again, and I got incorrect data again and so 4th times, then is correct again. But after 4th checked break point my program is freezing and I must press button with NAK, after that I got the first packet is correct.

    If I remove break point, I don't receive the correct data anymore, only the 1st data of packet 1.

    The model with breakpoint:

    -> sender sends packet 1

    . receiver got all data and stop for break point and press resume

    <- ACK ... all data is correct

    -> sender sends packet 2

    . receiver got all data and stop for break point and press resume

    <- NAK ... data is incorrect // #1

    -> sender sends packet 2

    . receiver got all data and stop for break point and press resume

    <- NAK ... data is incorrect // #2

    -> sender sends packet 2

    . receiver got all data and stop for break point and press resume

    <- NAK ... data is incorrect // #3

    . HERE IS THE PROGRAM IS FREEZING AND I NEED TO PRESS BUTTON TO SEND NAK. PRESS IT

    -> sender sends packet 2

    . receiver got all data and stop for break point and press resume

    <- ACK ... all data is correct

    -> sender sends packet 3

    . receiver got all data and stop for break point and press resume

    <- NAK ... data is incorrect // #1

    and so on

    Without breakpoint:

    First packet is ok, send the 2nd one and I always see incorrect data, even the very 4th packet has incorrect data

    Tesla DeLorean
    Guru
    December 9, 2015
    Posted on December 09, 2015 at 01:06

    It's not an endian issue, both are little endian.

    Normally the way you handle this is to take the bytes stream and manage them with a state machine. One that initially concentrates on waiting for the start character, and then the record number, and its complement, and then receiving the data. Doing the CRC as each byte arrives will reduce the latency in responding with an ACK if they match at the end.

    You can't treat this as a homogeneous lump of 1029 characters, succeed or fail. May be you can search for classic C implementations of the algorithm. Perhaps look at ST's IAP examples.

    After you get the CRC pass or fail, you should wait for the start character again

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..