No, you don’t need a function to do that!
In fact, a function is almost certainly the wrong way to do it!
Remember that Open-AT is entirely Event-driven; that is, your application is only ever “woken up” when the system has an Event for it.
Look at the basic AT command example in the SDK: the application just sets-up the handlers, and then “exits” - thereafter, it is only ever woken-up when the system detects that the command has been entered, and calls the handler.
Your FCM application needs to do the same: send the data, then exit. Your application will then be woken when an event happens; eg, MEM_RELEASE…
There is no need for any specific wait within your code!
i am sorry but i still didn’t understand how to make the sending process resume from the last place when the buffer is full. because in my thought, everytime the buffer is full then the system was halted and waiting for the resume event. but the resume event will trigger another routine and not continuing the previously halted process. i attach my application below, would you mind to go through it and give me an example or direction for what am i supposed to write in my code?
int sendFcmH ( u8 input)
{
res = adl_fcmSendData (Handle, (u8 *)&input, 1); // send 1 byte from the address of input
switch (res)
{
case ADL_FCM_RET_OK_WAIT_RESUME:
TRACE ((1,"ADL_FCM_RET_OK_WAIT_RESUME"));
break;
case ADL_RET_ERR_PARAM:
TRACE ((1,"ADL_RET_ERR_PARAM"));
break;
case ADL_RET_ERR_UNKNOWN_HDL:
TRACE ((1,"ADL_RET_ERR_UNKNOWN_HDL"));
break;
case ADL_RET_ERR_BAD_STATE:
TRACE ((1,"ADL_RET_ERR_BAD_STATE"));
break;
case ADL_FCM_RET_ERR_WAIT_RESUME:
TRACE ((1,"ADL_FCM_RET_ERR_WAIT_RESUME"));
break;
}
return 0;
}
void transmitZero ( int x)
{
int i = 1;
for (i==1;i<=x;i++)
{
sendFcmH(0x00);
}
}
void testHandler ()
{
adl_fcmSwitchV24State (Handle, ADL_FCM_V24_STATE_DATA);
}
bool fcmCtrlH (u8 event)
{
adl_atSendResponse (ADL_AT_UNS, "inside fcmCtrlH\n");
switch (event)
{
case ADL_FCM_EVENT_FLOW_OPENNED:
adl_atSendResponse (ADL_AT_UNS, "Flow Openned"); /* switching from AT mode to Data Mode*/
break;
case ADL_FCM_EVENT_V24_DATA_MODE:
adl_atSendResponse (ADL_AT_UNS, "Flow in Data Mode"); /* Sending data to the external app via v24 serial link*/
a=0;
c=0;
sendFcmH(0x01);
sendFcmH(0x7F);
transmitZero(2);
//transmit movement
for ( a=0;a<4;a++)
{
for ( c = 0; c<2;c++)
{
sendFcmH(0x90);
}
}
//Transmit data
a=0;
for (a==0;a<200;a++)
{
sendFcmH(0xFF);
}
break;
case ADL_FCM_EVENT_RESUME:
TRACE((1,"ADL_FCM_EVENT_RESUME"));
break;
case ADL_FCM_EVENT_MEM_RELEASE:
TRACE((1,"MEM_RELEASE"));
break;
}
return TRUE;
}
bool fcmDataH (u16 DataLen, u8 * Data)
{
adl_fcmSendData(Handle,Data,DataLen);
return TRUE;
}
You need to give your application some kind of “memory” so that it can “remember” where it was when it was last suspended.
In other words, you need to give your application some “memory” of its State - which is probably easiest done by writing your application as a Finite State Machine (FSM) - or just “State Machine” for short…
If there’s something stopping the buffer from emptying (eg, flow control) - then it could be infinite.
Even if it’s not not “infinite”, it could still be longer than the watchdog timeout.
As already noted, you should never put a busy-wait loop in an Open-AT application - always find an Even to wait for instead.
In this case, there is no need to wait for the buffer to be empty - the MEM_RELEASE event will tell you when FCM is ready to accept another adl_fcmSendData call.
The Watchdog in the OpenAT firmware is quite unforgiving - and it has to be, as the CPU is not only running your application but also doing all the GSM radio stuff as well. There are strict time limits on some GSM radio processes and the CPU HAS to handle the GSM firmware events in time - or the GSM network may detect there is something wrong with the module and de-register it from the network.
As awneil says - OpenAT is an EVENT-DRIVEN operating system - probably completely different from any other operating system you’ve ever programmed before. Pretty much every operation in OpenAT is done using Event/Call-back handlers, and long term operations are all done using State Machines.
Don’t EVER write code such as this:
while ( boolean test )
{
some operation;
};
As this will invariably trip the watchdog timer.
BTW, one advantage of a state machine is that you can completely define the entire task operation. That is, you know every state that the program is in, and how to transition between states.
There is a reasonable introduction to (finite) state machines here.
Hi all, I have followed your instruction about using FSM for my application. and thank god it worked. now i am continuing my application by combining the WIPSoft and the Fcm function. what i intend to make is an application which automatically request a web page containing my data from a web server. And after getting the data the app should send the preprocessed data into the UART1 using FcmSend Data. but there is a problem when i tried combining these function. the data that i saved when i accessing the web page is some kind of missing. and i cannot use the data to send it through the UART1.
I save the retrieved data into an array of string with the declaration like this : char* dataText[7]. The declaration was global. if i tried to use the data immediately after i retrieved it from the web page the data is good. but if i used it in another sub routine the data is lost and sometimes just filled with gibberish. i am still working on it now. i don’t think this is the perfect place to ask about it. so i just want to tell you that my fcm send Data is working perfectly now. If there’s any advice regarding the problem that i faced right now i will be more then happy to know it.