5 years, 7 months ago.

RTOS / SerialDriver problem

Hello

Have created a program using RTOS, where I run 4 threads. Each thread does it's thing almost perfectly.

The fourth is used to printf some chars to a device, which responds with an array back to mbed. Problem is, whenever I add the SerialDriver Read, getc or anything else it seems to either run out of memory or something else, which causes the whole program to stop running. I mean nothing runs at all.

I have tried also using the standard Serial library, but still no good. There's no indication whatsoever about where in the program it stops. it's never the same place/time it stops, ujust suddenly, no execution.

I have tried also to instanciate the Serial before main and so on.

Anybody have any idea?

int main()
{

    unsigned char serialBuffer[256];

    //SerialDriver DCU(p9, p10, 256, 256,NULL,serialBuffer);            // TX RX pins - Connected to MAX232 for REAL RS232.
    //SerialDriver pc(USBTX, USBRX);
    SerialDriver DCU(p9, p10);            // TX RX pins - Connected to MAX232 for REAL RS232.
    SerialDriver pc(USBTX, USBRX);
    DCU.baud(38400);                        // Baudrate of DCU
    DCU.format(8,SerialBase::None,2);       // 8 bits, None parity, 2 stop bits.
    pc.baud(115200);
    //DCU.attach(&dcurx_int);
    //flipper.attach(&flip, 0.1);
    //motor.rise(*motor_hall);
    wait_ms(500);

    Thread th1(flip);
    Thread th2(display);
    Thread th3(checkButton);
    //Thread th4(dcu_serial);
    th2.set_priority(osPriorityAboveNormal);
    th3.set_priority(osPriorityAboveNormal);
    relayBoard.reset();
    relayBoard.config_direction(PORT_A, 0x00);
    relayBoard.config_direction(PORT_B, 0x00);
    relayBoard.write(PORT_A, 0x00);
    relayBoard.write(PORT_B, 0x00);
    rly18(0);
    rly20(1);
    rly17(0);
    Menu.mode(PullUp);
    Left.mode(PullUp);
    Right.mode(PullUp);
    OK.mode(PullUp);
    SW1(2); // Set SW1 to RED
    SW2(2);
    SW3(2);
    SW4(2);
    setBackLight(128);
    ok = 0;
    a = 1;
    menuLayer = 0;
    //DSB_runningLogo();
    enableDCU();
    //Thread::wait(osWaitForever);

    const int readBufferLength= 22;
    unsigned char readBuffer[readBufferLength];
    unsigned char readBuffer2[readBufferLength];
    int receivedBytes= 0;
    int receivedBytes2= 0;
    unsigned char cpyBuffer[4];
    unsigned char cpyBuffer2[4];

    while(true) {
        
        DCU.puts((const char *)JF16);                                       // Output a string to DCU!
        for(int i = 0; i < readBufferLength;i++){
            while(!DCU.readable());
            readBuffer[i] = DCU.getc();
            receivedBytes = i;
        }
        
        //receivedBytes = DCU.read(readBuffer, readBufferLength);       // Read from DCU
        
        
        if(receivedBytes == 22) {
            memcpy(cpyBuffer,readBuffer+17,4);
            memset(readBuffer,0x00,readBufferLength);
            adc.A = (int)atoi((char*)cpyBuffer);
        }
        
        for (int i = 0; i < (sizeof(readBuffer)); i ++) {                // Readout data to PC
                pc.printf(" %2x", readBuffer[i]);                              // Printf it to PC
            }
            pc.printf("\r\n");
        /*
        Thread::wait(20);
        DCU.puts((const char *)JF48);                                       // Output a string to DCU!
        receivedBytes2 = DCU.read(readBuffer2, readBufferLength,30);       // Read from DCU
        if(receivedBytes2 == 22) {
            memcpy(cpyBuffer2,readBuffer2+17,4);
            memset(readBuffer2,0x00,readBufferLength);
            adc.B = (int)atoi((char*)cpyBuffer2);
        }
        */
        Thread::wait(400);
    }
}

Just for info, the transmitted bytes are: 0x02,0x01,0x05,0x24,0x4a,0x46,0x2d,0x31,0x36,0x26

The received ones are: 0x02,0x00,0x11,0x31,0x4a,0x46,0x46,0x30,0x30,0x31,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x36,0x38,0x38,0x5b - The last 4 bytes might change a little, nothing big.

posted by Christian Lerche 17 Apr 2015

1 Answer

5 years, 7 months ago.

It'sseems not to be the major problem but in the following code

unsigned char cpyBuffer[4];

memcpy(cpyBuffer,readBuffer+17,4);
 adc.A = (int)atoi((char*)cpyBuffer);

you fill the cpyBuffer with 4 chars, but you use it as string in the atoi function. the last character of the str must be '\x0' according of the c string use.

then the size of your buffer isn't enough large. you need 5 chars (the 4 you copy + the '\x0').

you have to modify it, if you want to get an correct return value from atoi.

char cpyBuffer[10];   // get enough space for a string.

memcpy(cpyBuffer,readBuffer+17,4);
cpyBuffer[4]='\x0';
 adc.A = (int)atoi((char*)cpyBuffer);

Accepted Answer

Oh, I didn't know that! Thanks for learning me something :-) I'll change that bit of code when I'm back in the shop on monday!

The main issue is still that I tried using only DCU.puts and DCU.read - And then it hangs. I'm trying to understand if the heap and stack might collide at some point, but I'm not sure how to use the solutions I've seen around the site.

I have tried adding error handlers - Even they wont print anything in the serial terminal. Might be stuck in some infinite loop somewhere, but as it always happens at different times, I think it might be RAM issue afterall.

Thanks for answering Raph!

EDIT 20-04-2015:

RAPH! YOU AMAZING MAN! You made me think... I thought about the char array that I printf/puts through the serialport, and they were NOT null-terminated. NULL-terminating the arrays actually made the difference. IT WORKS!!!! :D

Thanks man!

posted by Christian Lerche 18 Apr 2015