Nucleo -f429zi-144 with CAN communication

Dear Nada,

that can probably happen and I tried to understand why it is happening.

In Mbed’s crash report, on last line is show:
can ESR 0x0000.0000 + timeout status 0
And that came from can_frequency(int) function of ST implementation in can_api.c

Related issues:

From my understanding the frequency() method of Mbed CAN API, what call ST function, is usable only when is the CAN-BUS in Idle. So my recommendation is, place the frequency in to the constructor of CAN object. That will probably solve it, because we use it for a Car simulation and it is working for some time.
You can easily verify that with same method with reset buttons like I descripted above.

From this

CAN  can1(PB_8, PB_9);

to this

CAN  can1(PB_8, PB_9,250000);

and also cut-out can1.frequency(250000); from the code.

BR, Jan

Thank you so much Jan.

It’s fine now. I will keep you updated.

Now when I try to print a udp message in any thread the system crashed.

I will let you know if I couldn’t fix it.

Thank you.

Regards
Nada

Hello Jan,

Sorry again for my questions.

First , after trying to put the frequency n the constructor, CAN bus stop sending and receiving.

Second, Whenever I add a printf to my below program:

#include"mbed.h"
#include "EthernetInterface.h"
 
#define ECHO_SERVER_PORT   11000


//Serial  pc(USBTX, USBRX);                                       //tx,rx for Tera Term output

DigitalOut led1(LED1);// status LED
DigitalOut led2(LED2);// status LED
DigitalOut led3(LED3);// status LED

//Threads
Thread UDP_Client_Thread(osPriorityNormal, 2000);
Thread UDP_Server_Thread(osPriorityNormal, 2000);
Thread CAN_Read(osPriorityNormal, 2000);
Thread CAN_Write(osPriorityNormal, 2000);
Thread Process_UDP(osPriorityNormal, 2000);

char counter =0;

CAN  can1(PB_8, PB_9);        // CAN interface

//Mutex

Mutex Network_Mutex;
Mutex RecIP_Mutex;
 
// Network interface
EthernetInterface net;

static const char* mbedIP = "192.168.220.45";  //IP 
static const char* mbedMask = "255.255.252.0";  // Mask
static const char* mbedGateway = "192.168.220.1";    //Gateway
 
static const char* recvIP = "192.168.220.100";

typedef struct {
    char buffer[256];
    char* pFields[5];
    int can_id;
    char can_msg[8];
    int can_len;
    
} message_t;

MemoryPool<message_t, 32> mpool;
Queue<message_t, 32> queue;

message_t *message;

//define CAN ID
#define DCE_Steering_ID 0x600


// /////////////////////////////////////////////////////////////////////////////Splitting string Function//////////////////////////////////////////////////////////////////////////////////
void ParseFields(char* inputBuffer, char** pFields, uint32_t numFields, char* delimiterChars)
{
    char* pString = inputBuffer;
    char* pField;
    
    for(uint32_t i=0; i<numFields; i++)
    {
        pField = strtok(pString, delimiterChars);
 
        if(pField != NULL)
        {
            pFields[i] = pField;
            message_t *message = mpool.alloc();
            message->pFields[i]= pFields[i]; // copy the rxbuffer (recieved data from the truck) in the queue message
            queue.put(message);
            printf("splitted message: %s\r\n",  message);
        }
        else
        {
            pFields[i] = "";
        }
 
        pString = NULL; //to make strtok continue parsing the next field rather than start again on the original string (see strtok documentation for more details)
    }
}

void Processing_UDP_DATA_Thread()
{
    char* pFields[5];
    while(true)
    {
        osEvent evt = queue.get();
        
        if (evt.status == osEventMessage) 
        {
            message_t *message = (message_t*)evt.value.p;
            ParseFields(message->buffer, pFields, 5, ",");
            mpool.free(message);
        }
    }
}


//////////////////////////////////////////////////////////////////////////CAN Read////////////////////////////////////////////////////////////////////////////////////
void receive()
{
    CANMessage msg;//create empty CAN message
     while(1)
    {
        if(can1.read(msg))    // if message is available, read Into msg
        {
            //printf("Message received: %d\r\n" , msg.data[0]);           //display message  data
            led2 =  ! led2;        //toggle status LED
        }
    }
}
///////////////////////////////////////////////////////////////////////////CAN Write/////////////////////////////////////////////////////////////////////////////////////////////
void send()
{
    //printf("send....\r\n");
    
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
    
        if(can1.write(CANMessage(5 ,&counter,1)))
        
        {
            //printf("Message sent: %d\r\n",counter);//display
            
            counter++;                      //increment
            
            led1=!led1;                       //toggle status LEDelsecan1.reset();
        }
        ThisThread::sleep_for(500);
    }
}


//////////////////////////////////////////////////////////////////////////////UDP_Server///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Server()
{
    

    UDPSocket server;
    Network_Mutex.lock();
    server.open(&net);
    Network_Mutex.unlock();
    server.bind(10110);
    SocketAddress sockAddr;
 while(true)
 {
    char buffer[256];
    
    //printf("\nWaiting for UDP packet...\r\n");
    int n = server.recvfrom(&sockAddr, buffer, sizeof(buffer));
    buffer[n] = '\0';
    message_t *message = mpool.alloc();
    strcpy(message->buffer, buffer); // copy the rxbuffer (recieved data from the truck) in the queue message
    queue.put(message); // put the message in the queue
   // pc.printf("Received packet from: %s\n", sockAddr.get_ip_address());
   // printf("Packet contents : '%s'\r\n",buffer);
    //pc.printf("Sending Packet back to Client\n");
    server.sendto(sockAddr, buffer, n);
    
 }
    // Bring down the ethernet interface
    //net.disconnect();
    //pc.printf("Done\n");
}

//////////////////////////////////////////////////////////////////////////UDP_Client//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Client()
{
    
    //Buffer for output messages
        const char out_buffer[] = "very important data";
 
        //address of destination ip address and port
        RecIP_Mutex.lock();
        SocketAddress td_addr(recvIP, 11000);
        RecIP_Mutex.unlock();
        
        Network_Mutex.lock();
        UDPSocket td_sock(&net);
        Network_Mutex.unlock();
 
        // Loop to send data to Socket address "td_sock"
       while(true)
       {
            int ret = td_sock.sendto(td_addr, &out_buffer, sizeof(out_buffer));
            
         if(ret < 0)
         {
            Thread::wait(500);
         }
        }
}
 
int main()

{
    can1.frequency(500000); // set CAN bit rate to 1Mbps
    
   // printf("read....\r\n");
    net.set_network(mbedIP, mbedMask, mbedGateway);// my device address
    if (0 != net.connect())
        {
            printf("Error connecting\n\r");
            // ThisThread::sleep_for(1000);
            return -1;
        }
        else
        {
            printf("Connected Ethernet \n\r");
            led3=!led3;

        }
        
    UDP_Server_Thread.start(UDP_Server);
    UDP_Client_Thread.start(UDP_Client);
    CAN_Read.start(receive);
    CAN_Write.start(send);
    Process_UDP.start(Processing_UDP_DATA_Thread);
   /* while(1)
    {
               //display message  data
        led3 =  ! led3;        //toggle status LED
        ThisThread::sleep_for(100);
            
        
    }*/
}

I got this error

++ MbedOS Fault Handler ++

                                       FaultType: HardFault

                                                           Context:
                                                                   R0   : 00000000
  R1   : 2000C650
                 R2   : 00000000
                                R3   : 32312E33
                                               R4   : 01010101
                                                              R5   : 01000100
                                                                             R6   : 2000C64C
            R7   : 00000020
                           R8   : 2000C7F4
                                          R9   : 00000000
                                                         R10  : 20008268
                                                                        R11  : 2000B034
       R12  : 08014CC9
                      SP   : 2000C634
                                     LR   : 08004D5D
                                                    PC   : 080010E2
                                                                   xPSR : 41000200
  PSP  : 2000C610
                 MSP  : 2002FFD8
                                CPUID: 410FC241
                                               HFSR : 40000000
                                                              MMFSR: 00000082
                                                                             BFSR : 00000000
            UFSR : 00000000
                           DFSR : 00000008
                                          AFSR : 00000000
                                                         MMFAR: 00000000
                                                                        Mode : Thread
     Priv : Privileged
                      Stack: PSP

                                -- MbedOS Fault Handler --



                                                          ++ MbedOS Error Info ++
 Error Status: 0x80FF013D Code: 317 Module: 255
                                               Error Message: Fault exception
                                                                             Location: 0x80010E2
                Error Value: 0x200001B0
                                       Current Thread: application_unnamed_thread Id: 0x20003A20 Entry: 0x8009CFD StackSize: 0x7D0 StackMem: 0x2000C030 SP: 0x2000C634
       For more info, visit: https://mbed.com/s/error?error=0x80FF013D&tgt=NUCLEO_F429ZI
        -- MbedOS Error Info --

                               = System will be rebooted due to a fatal error =
                                                                               = Reboot count(=2) reached maximum, system will halt after rebooting

I don’t know what I’m doing wrong.

With the LPC1768 I was not getting this kind of errors, but I need to use the nucleo.

Please, help and your advise.

I will keep working on that.

Regards
Nada

Dear Jan,

I want you to have a look to my below program:

#include"mbed.h"
#include "EthernetInterface.h"
 
#define ECHO_SERVER_PORT   11000


//Serial  pc(USBTX, USBRX);                                       //tx,rx for Tera Term output

DigitalOut led1(LED1);// status LED
DigitalOut led2(LED2);// status LED
DigitalOut led3(LED3);// status LED

//Threads
Thread UDP_Client_Thread(osPriorityNormal, 2000);
Thread UDP_Server_Thread(osPriorityNormal, 2000);
Thread CAN_Read(osPriorityNormal, 2000);
Thread CAN_Write(osPriorityNormal, 2000);
Thread DCE_Steering_Thread(osPriorityNormal, 2000);


char counter =0;

CAN  can1(PB_8, PB_9);        // CAN interface

//Mutex

Mutex Network_Mutex;
Mutex RecIP_Mutex;
Mutex UDP_Buffer_Mutex;
Mutex CAN_Mutex;
 
// Network interface
EthernetInterface net;

static const char* mbedIP = "192.168.220.45";  //IP 
static const char* mbedMask = "255.255.252.0";  // Mask
static const char* mbedGateway = "192.168.220.1";    //Gateway
 
static const char* recvIP = "192.168.220.100";

typedef struct
{
    int can_id;
    char can_msg[8];
    int can_len;

} message_t;


MemoryPool<message_t, 16> mpool;
Queue<message_t, 16> queue;

char buffer_UDP[256];
char* pFields_UDP[5];

void ParseFields(char* inputBuffer, char** pFields, uint32_t numFields, char* delimiterChars)
{
    char* pString = inputBuffer;
    char* pField;
    
    for(uint32_t i=0; i<numFields; i++)
    {
        pField = strtok(pString, delimiterChars);
 
        if(pField != NULL)
        {
            pFields[i] = pField;
        }
        else
        {
            pFields[i] = "";
        }
 
        pString = NULL; //to make strtok continue parsing the next field rather than start again on the original string (see strtok documentation for more details)
    }
}

void DCE_Steering()
{
    //printf("send....\r\n");
    char buffer_Local[256];
    char* pFields_Local[5];
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
        UDP_Buffer_Mutex.lock();
        memcpy(pFields_Local,pFields_UDP,sizeof(pFields_UDP)); // copy the rxbuffer (recieved data from the truck) in the queue message
        UDP_Buffer_Mutex.unlock(); // put the message in the queue
        
        message_t *message = mpool.alloc();
        message->can_id = 0x600;
        message->can_len = 5;
        sprintf( message->can_msg,"%0.2f \n\r",pFields_Local);
        queue.put(message);
    }
}


//////////////////////////////////////////////////////////////////////////CAN Read////////////////////////////////////////////////////////////////////////////////////
void receive()
{
    CANMessage msg;//create empty CAN message
     while(1)
    {
        if(can1.read(msg))    // if message is available, read Into msg
        {
            //printf("Message received: %d\r\n" , msg.data[0]);           //display message  data
            led2 =  ! led2;        //toggle status LED
        }
    }
}
///////////////////////////////////////////////////////////////////////////CAN Write/////////////////////////////////////////////////////////////////////////////////////////////
void send()
{
    CANMessage  msg_Local;
    char can_msg[8];
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
        osEvent evt = queue.get();
        if (evt.status == osEventMessage)
        {
            message_t *message = (message_t*)evt.value.p;
            CAN_Mutex.lock();
            can1.write(CANMessage(message->can_id, message->can_msg, message->can_len));
            CAN_Mutex.unlock();
            mpool.free(message);

        }
        Thread::wait(500);
    }
}


//////////////////////////////////////////////////////////////////////////////UDP_Server///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Server()
{
    

    UDPSocket server;
    Network_Mutex.lock();
    server.open(&net);
    Network_Mutex.unlock();
    server.bind(10110);
    SocketAddress sockAddr;
    char buffer[256];
    char* pFields[5];
 while(true)
 {
    //printf("\nWaiting for UDP packet...\r\n");
    int n = server.recvfrom(&sockAddr, buffer, sizeof(buffer));
    buffer[n] = '\0';
    ParseFields(buffer, pFields, 6, ",");
    UDP_Buffer_Mutex.lock();
    memcpy(pFields_UDP, pFields,sizeof(pFields)); // copy the rxbuffer (recieved data from the truck) in the queue message
    UDP_Buffer_Mutex.unlock(); // put the message in the queue
   // pc.printf("Received packet from: %s\n", sockAddr.get_ip_address());
    //printf("Packet contents : '%s'\r\n",buffer);
    //pc.printf("Sending Packet back to Client\n");
    //server.sendto(sockAddr, buffer, n);
    
    ThisThread::sleep_for(100);
    
 }
    // Bring down the ethernet interface
    //net.disconnect();
    //pc.printf("Done\n");
}

//////////////////////////////////////////////////////////////////////////UDP_Client//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Client()
{
    
    //Buffer for output messages
        const char out_buffer[] = "very important data";
 
        //address of destination ip address and port
        RecIP_Mutex.lock();
        SocketAddress td_addr(recvIP, 11000);
        RecIP_Mutex.unlock();
        
        Network_Mutex.lock();
        UDPSocket td_sock(&net);
        Network_Mutex.unlock();
 
        // Loop to send data to Socket address "td_sock"
       while(true)
       {
            int ret = td_sock.sendto(td_addr, &out_buffer, sizeof(out_buffer));
            
         if(ret < 0)
         {
            Thread::wait(500);
         }
        }
}
 
int main()

{
    can1.frequency(500000); // set CAN bit rate to 1Mbps
    
    printf("read....\r\n");
    net.set_network(mbedIP, mbedMask, mbedGateway);// my device address
    if (0 != net.connect())
        {
            printf("Error connecting\n\r");
            // ThisThread::sleep_for(1000);
            return -1;
        }
        else
        {
            printf("Connected Ethernet \n\r");
            led3=!led3;

        }
        
    UDP_Server_Thread.start(UDP_Server);
    UDP_Client_Thread.start(UDP_Client);
    CAN_Read.start(receive);
    CAN_Write.start(send);
    DCE_Steering_Thread.start(DCE_Steering);
   /* while(1)
    {
               //display message  data
        led3 =  ! led3;        //toggle status LED
        ThisThread::sleep_for(100);
            
        
    }*/
}

Now whenever I addedd the memory pool, I’m getting this error below:

I don’t know what am doing wrong.

Please help. I want to use the memory pool cause I want to send diffrent data with the IDs

Regards
Nada

Dear Nada,

the Nucleo-F429ZI with Mbed OS 5.15.6 with frequency in constructor is working well. I am sure because I tested it. What I can not test is LPC1768 because I do not have this peace of hardware.
So try to use frequency in constructor only with Nucleo.

The source of the crash seems to be DCE_Steering.

BR, Jan

Thank you Jan,

Ok I will do it.

But why the DCE steering crashes the system. i shouldn’t add another thread or do you have a solution. I need to receive the data from the UDP client and then send only two values to a CAN device .

So I have to send the ID, message

Regards
Nada

From my point of view it is because the thread keep running and it doesn’t matter if there is something in the buffer or not.

Try to put the Can message to the queue directly from UDP thread.

BR, Jan

Thank you Jan,

I tried this actually but also keep crushing:

#include"mbed.h"
#include "EthernetInterface.h"
 
#define ECHO_SERVER_PORT   11000


//Serial  pc(USBTX, USBRX);                                       //tx,rx for Tera Term output

DigitalOut led1(LED1);// status LED
DigitalOut led2(LED2);// status LED
DigitalOut led3(LED3);// status LED

//Threads
Thread UDP_Client_Thread(osPriorityNormal, 2000);
Thread UDP_Server_Thread(osPriorityNormal, 2000);
Thread CAN_Read(osPriorityNormal, 2000);
Thread CAN_Write(osPriorityNormal, 2000);
// DCE_Steering_Thread(osPriorityNormal, 2000);


char counter =0;

CAN  can1(PB_8, PB_9,500000);        // CAN interface

//Mutex

Mutex Network_Mutex;
Mutex RecIP_Mutex;
Mutex UDP_Buffer_Mutex;
Mutex DCE_Buffer_Mutex;
Mutex CAN_Mutex;
 
// Network interface
EthernetInterface net;

static const char* mbedIP = "192.168.220.45";  //IP 
static const char* mbedMask = "255.255.252.0";  // Mask
static const char* mbedGateway = "192.168.220.1";    //Gateway
 
static const char* recvIP = "192.168.220.100";

typedef struct
{
    int can_id;
    char can_msg[8];
    int can_len;

} message_t;


MemoryPool<message_t, 32> mpool;
Queue<message_t, 32> queue;

char buffer_UDP[256];
char* pFields_UDP[5];

void ParseFields(char* inputBuffer, char** pFields, uint32_t numFields, char* delimiterChars)
{
    char* pString = inputBuffer;
    char* pField;
    
    for(uint32_t i=0; i<numFields; i++)
    {
        pField = strtok(pString, delimiterChars);
 
        if(pField != NULL)
        {
            pFields[i] = pField;
        }
        else
        {
            pFields[i] = "";
        }
 
        pString = NULL; //to make strtok continue parsing the next field rather than start again on the original string (see strtok documentation for more details)
    }
    
    UDP_Buffer_Mutex.lock();
    memcpy(pFields_UDP, pFields,sizeof(pFields)); // copy the rxbuffer (recieved data from the truck) in the queue message
    UDP_Buffer_Mutex.unlock(); // put the message in the queue
}

/*void DCE_Steering()
{
    //printf("send....\r\n");
    char buffer_Local[256];
    char* pFields_Local[5];
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
        DCE_Buffer_Mutex.lock();
        memcpy(pFields_Local,pFields_UDP,sizeof(pFields_UDP)); // copy the rxbuffer (recieved data from the truck) in the queue message
        DCE_Buffer_Mutex.unlock(); // put the message in the queue
        
        message_t *message = mpool.alloc();
        message->can_id = 0x600;
        message->can_len = 5;
        for(int n = 0; n < 5; n++) 
        {
            sprintf(message->can_msg,"%0x",n,pFields_Local[n]);         
        }
        queue.put(message);
    }
}*/


//////////////////////////////////////////////////////////////////////////CAN Read////////////////////////////////////////////////////////////////////////////////////
void receive()
{
    CANMessage msg;//create empty CAN message
     while(1)
    {
        if(can1.read(msg))    // if message is available, read Into msg
        {
            //printf("Message received: %d\r\n" , msg.data[0]);           //display message  data
            led2 =  ! led2;        //toggle status LED//printf("send....\r\n");
        }
    }
}
///////////////////////////////////////////////////////////////////////////CAN Write/////////////////////////////////////////////////////////////////////////////////////////////
void send()
{
    CANMessage  msg_Local;
    char can_msg[8];
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
        osEvent evt = queue.get();
        if (evt.status == osEventMessage)
        {
            message_t *message = (message_t*)evt.value.p;
            CAN_Mutex.lock();
            can1.write(CANMessage(message->can_id, message->can_msg, message->can_len));
            CAN_Mutex.unlock();
            mpool.free(message);

        }
        Thread::wait(500);
    }
    //printf("send....\r\n");
    /*char buffer_Local[256];
    char* pFields_Local[5];
    while(1)
    {//send  value  to  CAN  bus  AND  monitor  return value    to    check    if    CAN    message    was    sent successfully. If so display, increment and toggle.
        UDP_Buffer_Mutex.lock();
        memcpy(pFields_Local,pFields_UDP,sizeof(pFields_UDP)); // copy the rxbuffer (recieved data from the truck) in the queue message
        UDP_Buffer_Mutex.unlock(); // put the message in the queue
        
        can1.write(CANMessage(0x600 ,pFields_Local[2],1));
        led1=!led1;                       //toggle status LEDelsecan1.reset();
        ThisThread::sleep_for(500);
    }*/
    
}


//////////////////////////////////////////////////////////////////////////////UDP_Server///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Server()
{
    

    UDPSocket server;
    Network_Mutex.lock();
    server.open(&net);
    Network_Mutex.unlock();
    server.bind(10110);
    SocketAddress sockAddr;
    char buffer[256];
    char* pFields[5];
 while(true)
 {
    //printf("\nWaiting for UDP packet...\r\n");
    int n = server.recvfrom(&sockAddr, buffer, sizeof(buffer));
    buffer[n] = '\0';
    //ParseFields(buffer, pFields, 6, ",");
    message_t *message = mpool.alloc();
    message->can_id = 0x600;
    message->can_len = 5;
    message->can_msg[0] = buffer[0] ;       //LSB
    message->can_msg[1] = buffer[1]; //MSB
    message->can_msg[2] = buffer[2];
    message->can_msg[3] = buffer[3]; //MSB
    message->can_msg[4] = buffer[4];
    queue.put(message);
   // pc.printf("Received packet from: %s\n", sockAddr.get_ip_address());
    //printf("Packet contents : '%s'\r\n",buffer);
    //pc.printf("Sending Packet back to Client\n");
    //server.sendto(sockAddr, buffer, n);
    
    ThisThread::sleep_for(100);
    
 }
    // Bring down the ethernet interface
    //net.disconnect();
    //pc.printf("Done\n");
}

//////////////////////////////////////////////////////////////////////////UDP_Client//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UDP_Client()
{
    
    //Buffer for output messages
        const char out_buffer[] = "very important data";
 
        //address of destination ip address and port
        RecIP_Mutex.lock();
        SocketAddress td_addr(recvIP, 11000);
        RecIP_Mutex.unlock();
        
        Network_Mutex.lock();
        UDPSocket td_sock(&net);
        Network_Mutex.unlock();
 
        // Loop to send data to Socket address "td_sock"
       while(true)
       {
            int ret = td_sock.sendto(td_addr, &out_buffer, sizeof(out_buffer));
            
         if(ret < 0)
         {
            Thread::wait(500);
         }
        }
}
 
int main()

{
    //can1.frequency(500000); // set CAN bit rate to 1Mbps
    
    printf("read....\r\n");
    net.set_network(mbedIP, mbedMask, mbedGateway);// my device address
    if (0 != net.connect())
        {
            printf("Error connecting\n\r");
            // ThisThread::sleep_for(1000);
            return -1;
        }
        else
        {
            printf("Connected Ethernet \n\r");
            led3=!led3;

        }
        
    UDP_Server_Thread.start(UDP_Server);
    UDP_Client_Thread.start(UDP_Client);
    CAN_Read.start(receive);
    CAN_Write.start(send);
    //DCE_Steering_Thread.start(DCE_Steering);
   /* while(1)
    {
               //display message  data
        led3 =  ! led3;        //toggle status LED
        ThisThread::sleep_for(100);
            
        
    }*/
}

I’m trying to figure out what I’m doing wrong but reach no solution.

Regards
Nada

Dear Nada,

I tried (Nucleo-F429ZI MbedOS 5.15.6) your code (copy&paste) and it is working, no crash.

BR, Jan

Thank you so much Jan,

Yes yesterday I tried mt best to fix it. Really I appreciete your support.

My main controller is the Nucleo, the LPC1768 is only for testing.

Now, I’m trying to assign char* to can msg which is char(byte) and still facing issues.

Regards
Nada

Hello Nada,

Now, I’m trying to assign char* to can msg which is char(byte) and still facing issues.

It is not an issue of your code but probably about your UDP sender application. Your application probably pass the data to the socket as string and not as bytes.

Example:
When you send this string 01 02 03 04 05 as string via UDP then your server will receive string of chars 14bytes long.
But when you will send same string as hex values via UDP then your server will receive 5 bytes.

It is also possible to handle it on the Nucleo side but it is pointless I think.

BR, Jan

Thank you Jan,

I will recieve the data from the client as a string of float values and then I will send it through CAN bus.

When I split the string the values will be stored in a char* variable and when I tried to assign it to the CAN msg, I had an error.

That’s why I have to convert it.

Thank you so much for your help

Regards
Nada

Dear Jan,

I hope yoy are doing well. I want to ask if we can put two diffrent messages in the queue.

For example:

typedef struct
{
    int can_id;
    char can_msg[8];
    int can_len;

} message_t;


MemoryPool<message_t, 32> mpool;
Queue<message_t, 32> queue;

 message_t *message = mpool.alloc();
    message->can_id = 120;
    message->can_len = 8;
    message->can_msg[0]=  0x01;
    message->can_msg[1]=0x03;
    message->can_msg[2]=0x04;
    message->can_msg[3]=0x00;
    message->can_msg[4]=0x00;
    message->can_msg[5]=0x00;
    message->can_msg[6]=0x00;
    message->can_msg[7]=0x00;
    queue.put(message);

 message_t *message_1 = mpool.alloc();
    message->can_id = 120;
    message->can_len = 8;
    message->can_msg[0]=  0x01;
    message->can_msg[1]=0x02;
    message->can_msg[2]=0x00;
    message->can_msg[3]=0x00;
    message->can_msg[4]=0x00;
    message->can_msg[5]=0x00;
    message->can_msg[6]=0x00;
    message->can_msg[7]=0x00;
    queue.put(message_1);

For receiving I don’t know how I can pull the data from the queue.

Please you help and support.

I want to send different messages via can using the same ID but different data.

Regards
Nada

Hi Nada,

yeah, I’m well, thank you.

From my point of view it is possible and that is why it is called Queue.
The basis of what you need is in example of (end of page) Queue - API references and tutorials | Mbed OS 6 Documentation

BR, Jan

Hi Jan

Thank you for your reply. I saw this example but for me I’m sending the can msg with different values am not sending different variables the same variable with different values in the sam e thread.

Regards
Nada

Dear Nada,

I am not sure if I understand your idea.
Queue<message_t, 32> queue; the number 32 represent how much message_t you can store in the queue. So in this case you can store 32 message_t in your queue, and of course you can fill same, similar or different messages in to the Queue.

Simulation (MbedOS 5.15.6)
#include "mbed.h"                                           // MbedOS 5.15.6
#define MAX 3                                               // max messages

DigitalOut myled1(LED1), myled2(LED2), myled3(LED3);

Thread thread_CanMessage_filler;
Thread thread_CanMessage_worker;

Queue<CANMessage, MAX > queue;
MemoryPool<CANMessage, MAX > mpool;

InterruptIn btn(BUTTON1);
volatile bool flag = false;

void pressed(){
    flag = true;
}

void filler(){
    printf("Filler thread start\n");
    while(1){
        if(!queue.full()){
            CANMessage *msg = mpool.alloc();;
            // simulation of filling message from somewhere
            msg->id = 0x120;
            msg->len = 3;
            for(int i = 0; i < msg->len; i++){
                msg->data[i] = (char)rand()%256;
            }
            queue.put(msg);
            printf("Fill msg - ID: %9x Len: %d Data: %2x %2x %2x %2x %2x %2x %2x %2x\n", 
                msg->id, msg->len, msg->data[0], msg->data[1],msg->data[2], msg->data[3],msg->data[4], msg->data[5],msg->data[6],msg->data[7]);
            myled2 = !myled2;
        }
        else printf("Queu is full press User button!\n");   // queue is full 
        ThisThread::sleep_for(500);
    }

}
void work(){
    printf("Worker thread start\n");
    while(1) {
        if (flag) {
            while(!queue.empty()){
                osEvent evt = queue.get();
                if (evt.status == osEventMessage) {
                    CANMessage *wmsg = (CANMessage*)evt.value.p;
                    // do something with message
                    printf("Read msg - ID: %9x Len: %d Data: %2x %2x %2x %2x %2x %2x %2x %2x\n", 
                        wmsg->id, wmsg->len, wmsg->data[0], wmsg->data[1],wmsg->data[2], wmsg->data[3], wmsg->data[4],wmsg->data[5], wmsg->data[6], wmsg->data[7]);
                    myled3 = !myled3;
                    mpool.free(wmsg);
                }
                ThisThread::sleep_for(100);
            }
            flag = false;
        }
    }
}
 
int main (void) {
    printf("Simulation start\n");
    // this will simulate incomming messages
    thread_CanMessage_filler.start(&filler);
    // this will simulate processing of messages
    thread_CanMessage_worker.start(&work);
        // button will simulate a trigger for messages processing
    btn.fall(callback(&pressed));

    while(1){
        myled1 = !myled1;
        thread_sleep_for(500);
    }
}
Simulation (MbedOS 6.12)
#include "mbed.h"                                           // MbedOS 6.12
#define MAX 3                                               // max messages

DigitalOut myled1(LED1), myled2(LED2), myled3(LED3);

Thread thread_CanMessage_filler;
Thread thread_CanMessage_worker;

Queue<CANMessage, MAX > queue;
MemoryPool<CANMessage, MAX > mpool;

InterruptIn btn(BUTTON1);
volatile bool flag = false;

void pressed(){
    flag = true;
}

void filler(){
    printf("Filler thread start\n");
    while(1){
        if(!queue.full()){
            CANMessage *msg = mpool.try_alloc();
            // simulation of filling message from somewhere
            msg->id = 0x120;
            msg->len = 3;
            for(int i = 0; i < msg->len; i++){
                msg->data[i] = (char)rand()%256;
            }
            queue.try_put(msg);
            printf("Fill msg - ID: %9x Len: %d Data: %2x %2x %2x %2x %2x %2x %2x %2x\n", 
                msg->id, msg->len, msg->data[0], msg->data[1],msg->data[2], msg->data[3],msg->data[4], msg->data[5],msg->data[6],msg->data[7]);
            myled2 = !myled2;
        }
        else printf("Queu is full press User button!\n");   // queue is full 
        ThisThread::sleep_for(500ms);
    }

}
void work(){
    printf("Worker thread start\n");
    CANMessage *wmsg;
    while(1) {
        if (flag) {
            while(!queue.empty()){
                if (queue.try_get(&wmsg)) {
                    // do something with message
                    printf("Read msg - ID: %9x Len: %d Data: %2x %2x %2x %2x %2x %2x %2x %2x\n", 
                        wmsg->id, wmsg->len, wmsg->data[0], wmsg->data[1],wmsg->data[2], wmsg->data[3], wmsg->data[4],wmsg->data[5], wmsg->data[6], wmsg->data[7]);
                    myled3 = !myled3;
                    mpool.free(wmsg);
                }
                ThisThread::sleep_for(100ms);
            }
            flag = false;
        }
    }
}
 
int main (void) {
    printf("Simulation start\n");
    // this will simulate incomming messages
    thread_CanMessage_filler.start(&filler);
    // this will simulate processing of messages
    thread_CanMessage_worker.start(&work);
        // button will simulate a trigger for messages processing
    btn.fall(callback(&pressed));

    while(1){
        myled1 = !myled1;
        thread_sleep_for(500);
    }
}

BR, Jan

Hi Jan,

Thank you for your contiuas support.

In your example, each the thread is started the queue will bi filled with the can message with different values but What I need something like this:

in the same thread writting two different message to the queue after each other:

CANMessage *msg = mpool.alloc();
CANMessage *msg _1= mpool.alloc();

msg->id = 0x120;
            msg->len = 3;
            for(int i = 0; i < msg->len; i++){
                msg->data[i] = (char)rand()%256;
            }
            queue.put(msg);

msg_1->id = 0x120;
            msg_1->len = 3;
            for(int i = 0; i < msg->len; i++){
                msg_1->data[i] = (char)rand()%256;
            }
            queue.put(msg_1);

Can I do this in the same thread.

Regards

Dear Nada,

I still do not understand the context but yes, you can do this, but from my point of view it is still same in the princip.

For example when you make a function what will fill CAN message to the queue and call it 2 times in a place

// includes, objects, etc
#define MAX 3   
Queue<CANMessage, MAX > queue;

bool FillMsgToQeue(CANMessage *msg){
    if(!queue.full()){
        queue.put(msg);
        printf("Fill msg - ID: %9x Len: %d Data: %2x %2x %2x %2x %2x %2x %2x %2x\n", 
                msg->id, msg->len, msg->data[0], msg->data[1],msg->data[2], msg->data[3],msg->data[4], msg->data[5],msg->data[6],msg->data[7]);
        return true;
    }
    else return false; // mean the queue is full
}
// rest of code

BR, Jan

Thank you Jan,

Your answer is what I need, Thank you so much.

The last question pleae Jan,

I want ot ask you if I can control a CANopen motor using Mbed.

I want to translate the following program to Mbed.

//in this example the operationmode will be set to velocity mode and the state machine will be switched on

//1. Step: mapping the frequently used SDO´s

map U16 ControlWord as output 0x6040:00
map S08 OperationMode as output 0x6060:00
map S16 TargetVelocity as output 0x6042:00

#include "wrapper.h"


//2. Step: call main function and set the speed and mode of operation

void user()
{
	
	//sleep(5000);                      // wait 5000 ms (optional if needed)
	Out.OperationMode = 2;				// set the mode of operation to velocity mode (with mapping, line 5-7)
	//od_write(0x6060,0x00, 2);			// would also set the mode of operation to velocity mode (without mapping, line 5-7)
		
	Out.TargetVelocity = 200;			// set the target velocity to 200 rpm (basicvalue)(with mapping, line 5-7)
	//od_write(0x6042,0x00, 200);		// set the target velocity to 200 rpm (basicvalue)(without mapping, line 5-7)
		
//3. Step: switch on the state machine 

	Out.ControlWord = 0x6;				// switch to the "enable voltage" state
	do 	{
		yield();						// waiting for the next cycle (1ms)
		}
		while ( (od_read(0x6041, 0x00) & 0xEF) != 0x21);   // wait until drive is in state "enable voltage"
	
	// checking the statusword (0x6041) for the bitmask: xxxx xxxx x01x 0001
	
	Out.ControlWord = 0x7;				// switch to the "switched on" state
	do 	{
		yield();						// waiting for the next cycle (1ms)
		}
		while ( (od_read(0x6041, 0x00) & 0xEF) != 0x23);   // wait until drive is in state "switched on"	
	// checking the statusword (0x6041) for the bitmask: xxxx xxxx x01x 0011	
		
	Out.ControlWord = 0xF;				// switch to the "enable operation" state and starts the velocity mode
	do 	{
		yield();						// waiting for the next cycle (1ms)
		}
		while ( (od_read(0x6041, 0x00) & 0xEF) != 0x27);   // wait until drive is in state "operation enabled"	
	// checking the statusword (0x6041) for the bitmask: xxxx xxxx x01x 0111	
		
	while(true)							// endless loop
	{yield();}	                      	// waiting for the next cycle (1ms)
		
}	

I saw example to use canopen with mbed but it’s not enough.

Please your advice regarding this matter.

Regards
'Nada

Dear Nada,

share the link of mentioned example please.

CANopen is CAN-based higher-layer protocol for embedded control system. So probably it is possible but you need a CANopen library, maybe - GitHub - CANopenNode/CANopenNode: CANopen protocol stack.
There is also old project where it is used under Mbed - GitHub - Alphatronics/mbed-os-example-canopen: An example program runnig CANopenNode running on NUCLEO_F091RC mbed platform

Anyway, I have no experiences with CANopen and also I have no harware for testing, so probably will be better to create new topic about CANopen.

BR, Jan