Use Cellular Interface to access LTE module

I want to use FreeRTOS in my next project, it use a LTE Module to:

  • Create Socket and connect to TCP Server (Receive / Send)
  • SMS (Receive / Send)
  • FTP (Download/ Upload)
  • voice call
  • other: NTP / …

I Read the Cellular Interface and tried the demo “Lab-Project-FreeRTOS-Cellular-Demo” (mqtt_mutual_auth_demo.sln)

I opened the project and connect to a SARA-R4 EVK board, after step into the code, I have some questions:

I ever use many 2/3/4G Modules and control it by 8 bit MCU, so I used to write a switch case as state machine. When I have job to do, I put it to queue, send CMD, receive ack from ISR, parse it and then do the next step.

When I use FreeRTOS, it looks so different, it seems I can do one job in a single function, for example:
A FTP download, it needs 4、5 AT commands to complete to job, so I need write 4、5 labels in switch case to deal with it. (and more for the ACK of OK, ERROR, timeout)
After using FreeRTOS Cellular Interface, I can send message, wait ACK( using xQueueReceive) and then do the next, it seems so convenient!

But I noticed that It just use a prefix table to decide the received message is ACK or URC message(event from module), as shown below:

const char * CellularUrcTokenWoPrefixTable[] ={ "RDY" };

cellular_pktio.c:

static _atRespType_t _getMsgType( const CellularContext_t * pContext,
                                  const char * pLine,
                                  const char * pRespPrefix )
{
    _atRespType_t atRespType = AT_UNDEFINED;
    CellularATError_t atStatus = CELLULAR_AT_SUCCESS;
    bool inputWithPrefix = false;
    bool inputWithSrcPrefix = false;
    if( pContext->tokenTable.pCellularUrcTokenWoPrefixTable == NULL )
    {
        atStatus = CELLULAR_AT_ERROR;
        atRespType = AT_UNDEFINED;
    }
    else if( urcTokenWoPrefix( pContext, pLine ) == true )
    {
        atRespType = AT_UNSOLICITED;
    }
    else
    {
        /* Check if prefix exist in pLine. */
        ( void ) Cellular_ATIsPrefixPresent( pLine, &inputWithPrefix );
        if( ( inputWithPrefix == true ) && ( pRespPrefix != NULL ) )
        {
            /* Check if SRC prefix exist in pLine. */
            atStatus = Cellular_ATStrStartWith( pLine, pRespPrefix, &inputWithSrcPrefix );
        }
    }
...
...
}

The demo project just define one URC prefix as ‘RDY’ (in cellular_r4.c)
I will have many URCs in real project, the problem is, not all URCs have so simple structure.

If I set CREG/ CEREG / CGREG = 2, then it will send URC when state changed, and message format is just the same as AT+CREG/CEREG/CGREG command ACK, is it can really tell the difference? (the received message is a command ack, or a URC from module?)

After opened a TCP Socket, when Server Send something to the module, it will send a URC with prefix header, a new line, and lots of data, how the incoming TCP data be received correctly?

Is there any demo project that do the TCP Socket Connection?

the Cellular interface looks so good, it can simplify the implementation if it works…, hope someone can give suggestions about how the interface parse general AT CMD ACK and URC message

Hi Ntustzeus,

Thank you for your interesting in FreeRTOS-Cellular-Interface. I summarize your questions into three and hope I understand your questions well.

1. Distinguish between URC and AT command ACK
Cellular interface library can recognize two kinds of URC.

  • URC with prefix : The URC must have the prefix format “<prefix char only string>: …”, for example “+CREG: …”
  • URC without prefix : The URC is fixed string, for example “RDY”. They must be defined in CellularUrcTokenWoPrefixTable

Cellular modem porting handles URC in URC handler, for example SARA_R4 porting handle URC in the file.
URC not related to cellular API may not be handled in cellular modem porting.
Users of FreeRTOS Cellular Interface can still use Cellular_RegisterUrcGenericCallback to register the URC callback.
The callback function will be called if the URC is not handled by cellular modem porting.

The function you mentioned, _getMsgType, is the logic to tell if the message is URC or AT command ACK.

Take the CREG for example,

at+creg?
<---- We are sending AT command to modem and expecting AT command ACK.
+CREG: 2,1,"2C89","341B50D",8
<---- This line corresponds to AT command expected response. It will be added to 
      CellularATCommandResponse_t and will not be regarded as URC.

OK
<---- The AT command is complete.

+CREG: 1,"2C89","341B50D",8
<---- We are not sending any command to modem. This line will be recognized as URC.
      The message is passed to URC handler for further processing.

2. TCP socket data received
Currently, FreeRTOS Cellular Interface supports buffer access mode.
The socket data is retrieved through AT command response.
URC is only used to notify data received.

3. Demo project for TCP socket connection
We have integration test to test TCP socket connect, send and receive with echo server.
The code can be referenced as an example.

It is still difficult to support various cellular modem.
For example, some cellular modem doesn’t use fixed token to indicate AT command success or fail or their URC is not fixed string and not in the format with prefix as expected.
We are trying to support them in cellular modem porting layer.
Users of FreeRTOS cellular interface don’t have to take care of the difference.

Please let me know if there is question need more information.
If you find any issue or you want to contribute to the FreeRTOS Cellular Interface,
you are very welcome to create issue or pull request in the repository.

Thanks for the replay

I’m still running the demo project(windows version) to see how it works, and I got many great ideas from it.

I think it is a great goal to support all cellular modems and provide unified APIs to users, it’s real cool, but as a embedded developer, we have some considerations:

  • MCU is resource limited, even when I use a 32 bit version. In general case, we just use few functions in one project for specific purpose. the MCU may not afford if the cellular interface has large size.

  • When I read the tutorial / Documentation / examples about the interface, it doesn’t provide instruction(steps) about how to port the interface to my project, especilly about the custom parts

when I read the tutorial(offical)(FreeRTOS Cellular Library)(GitHub),the only info I found about how to construct the interface is: “It is recommended that you start by cloning the implementation of one of the existing modems, then make modifications where your modem’s vendor-specific (non-3GPP) AT commands are different.”

I think it is not enough to port the interface to a new project. We need more clear instructions about how to organize these files(custom part), any suggestions about folder/file naming rule and where to place them?

From demo project, I got following folder structure:

The cellular folder in lib is provided in document so I can just move it to my project and modify files in folder “Cellular_R4”, but I can’t find the instructions/suggestions about files in folder “source”.
We have a “Cellular” folder and some files inside, but also some files like “cellular_setup.c”/“demo_config.h”/“logging_levels.h”/“logging_stack.h” in the root of source folder.

I don’t know what is the correct way to organize these files (if I want to treat them as independent software module).
The cellular interface related files split into many folders but not gathered in one, I think it make things harder to work with it.

So, if there is a guide can show us the steps to port/organize the interface would relly helpful. (maybe with demo project of popular MCU like ST32/PIC32/Atmel SAM Series/…).

what is the entry point that I should include to use the cellular interface?

I think if there is a minimal interface that only include few Standard AT CMDs and we can easily make it work, then we can easily add our working flow too. that will be a good start for us to implement other modules~

Thanks for the great interface, and hope we can make it work easier

Thank you for your feedback.
I would like to provide some link first as a beginning.

API reference
The cellular APIs, configurations, design overview, memory requirement and porting guide can be found in this page.

Porting guide
This page is for the developers who want to use cellular interface in their platform.
The first thing is to implement the communication interface to interact with cellular modem. Then the configuration macro file, cellular_conifg.h. The last thing is the platform dependency. FreeRTOS-Cellular-Interface runs on FreeRTOS. The platform dependency files, cellular_platform.h and cellular_platform.c, describe the dependency between them. They can be copied from the demo project.

Porting module guide
This page is for the developers who want to port new cellular module.
The guide provides the steps to port new cellular module, including the folder/file naming rule, module porting interface… After you have the idea about the porting steps, it is suggested to start the porting by cloning a existing cellular module and make modification.

These documents may not cover every detail.
If you have any topic you want to know more, please reply again in the thread.

I will close this issue since no longer updated. Please open a new issue if you have other feature requests or suggestions.