How to send a Hexa data using adl_fcmSendData

Dear all,

I want to send some hexa data using FCM flow manager. I tried to use the adl_fcmSendData() with several ways, first i use it to send a string “this is a data mode” (because i use the switch to change from the AT mode into Data mode) and it worked. after that i tried to change the data into array of hexa :
data[10] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}. And the data was also successfully sent. But when i tried to send a single hexa data : adl_fcmSendData(Handle,0x01,1); the data couldn’t be sent. i tried to send it several times using a loop but the data became another random data which i didn’t want to send.

i thought at first that Wavecom didn’t support to send a single hexa data. But when i implement the method to automatically send back every input data from UART 1. the method work smoothly. this is the method :
bool fcmDataHandler (u16 DataLen, u8 * Data)
{
adl_fcmSendData(Handle,Data,DataLen); // this function is to get the input data, and return it right away into the sender.

return TRUE;

}

is there any explanation for this behaviour?

Best Regards,
Okky kusuma

Hiya,

This is attempting to send 1 byte from memory address 0x01 - which you may or may not have access to, and is certainly not what you intended.

Here is the definition of fcm_sendData()

s8 adl_fcmSendData  (  u8  Handle, 
         u8 *  Data, 
         u16  DataLen );

Note that the data being sent is a pointer to u8.

To send one byte of data, do something like this:

u8 myData[10];

myData[0] = 0x01;
adl_fcmSendData(myHandle, myData, 1);

ciao, Dave

Hiya Dave,

i’ve followed your instruction. and i wrote a function to send a single byte. and i made this function :

void sendFcmH (u8 input)
{
u8 * buffer;
buffer = input;
adl_fcmSendData (Handle, buffer,1);
}

but still it didn’t work. is there something that i miss?

thanx for the quick reply!

Best Regards,
Hade

I’ve made it. thanx a lot Dave. but i still don’t get it. why i couldn’t send my data using my alogarithm? because the only difference between yours and mine is in the variable where i store my data.
in your code u use an array myData[10]. and you fill the first array myData[0] with the hex data.
in my code i only make a single variable u8 myData; and fill the variable with the hex data.

but the result is so different. i wonder why. would you mind to explain it a little for me?

Best Regards,
Okky kusuma

Hiya,

In this function, you’ve missed allocating any memory to the u8 pointer.

u8 * buffer;

This creates a variable of type u8 pointer - but doesn’t allocate any memory for data. Your next line

buffer = input;

essentially sets the pointer value (i.e. the address, NOT the data) to be the value of input.

My demo code with the array of u8 works because an array in C can also be treated as a pointer to a pre-defined area of memory.

Here are a couple of functions that should do the same thing as you intend in yours (note that I haven’t tested these!).

void sendFcmH (u8 input)
{
    u8 *buffer;                          // create a variable of type u8 pointer

    buffer = adl_memGet(sizeof(u8) * 1); // reserve 1 byte of memory from the heap
    *buffer = input;                     // copy the value of input to the location pointed
                                         // to by the address of buffer
    adl_fcmSendData (Handle, buffer,1);  // send the data
    adl_memRelease(buffer);              // release the allocated memory
}

or

void sendFcmH (u8 input)
{
    adl_fcmSendData (Handle, (u8 *)&input, 1); // send 1 byte from the address of input
}

Pointers can do your head in. Grab your favourite C textbook and have another read of the section on pointers.

Just remember that in OpenAT the ‘standard’ memory allocation functions (malloc, calloc, realloc & free) do not exist. ald_memGet() is analogous to malloc(), and adl_memRelease() is analogous to free().

Hope this helps.

Ciao, Dave

Just to echo that this is standard, basic, textbook ‘C’ stuff - nothing specifically to do with Wavecom or Open-AT.

You might find it easier to start by gaining familiarity with the ‘C’ language in a more “conventional” envoronment - eg, a PC - before adding the complications of embedded systems in general and Open-AT in particular…!

There are some general programming books listed here: keil.com/books/

Hi all, Thank you for the explanation. But i need a bit more help on my work. I am trying to access a single character from my char* dataText[5].
so before i implemented it on my wavecom application, i tested it on my win32 application console using visual C.
this is the code

#include <stdio.h>
#include <string.h>

int main ()
{
	char* dataText[6];

	dataText[0]="okkyKusuma";
	
	for (int i=0; i<7; i++)
	{
		char x = dataText[0][i];				// this is the part where i access the single character from my data.
		printf("letter number %d: %c\n",i,x);		        // and printed it to the screen
	
	}

return 0;
}

And the test program worked program and showed an output like this :

letter number 0: o
letter number 1: k
letter number 2: k
letter number 3: y
letter number 4: K
letter number 5: u
letter number 6: s

but when i tried to use the same method in my wavecom application, the result from accessing a single character went to disaster. this is the code :

char* dataText[6];
dataText[1]="OkkyKusuma";

	for (int i=0; i<7; i++)
	{
		char letter = dataText[1][i];				                // this is the part where i access the single character from my data.
		adl_atSendResponse (ADL_AT_UNS, letter);		        // and printed it to the screen
	}

The output from my code is a giberish code with like this :

p'xhK`p'xhK`p'xhK`p'xhK`p'xhK`p'xhK`p'xhK`
RpÕÒ!"C!Æ`¡ˆ        sÕBh

could somebody give me a clue where did i go wrong?? Thank you.

Best regards,
Hade

I’m afraid it’s that basic, textbook ‘C’ again!

char* dataText[6];

That is not an array of 6 chars - that is an array of 6 pointers to char :exclamation:

I think you really need to go back to basics, get a good ‘C’ text book or tutorial, and work through it from the beginning.

You currently seem to be building on rather shaky foundations.

[edit]
eg, try this: publications.gbdirect.co.uk/c_book/

Hiya,

Not only have you declared an array of 6 pointers to char (as noted by awneil), the line:

is not standard C.

You cannot assign a constant string to a pointer except during initialization. This is common complaint/problem.

I don’t know why it works on your Visual C example - maybe this construct is a Microsoft ‘Enhancement’ to the C language. OpenAT uses the GCC C compiler by default, and GCC is installed with M2M Studio.

It’s really time that you got hold of a good C textbook - one of my favourites is “A Book on C” by Al Kelly and Ira Pohl. My version is quite old, but it looks as though the book has been updated in the last few years.

Read the section on pointers, re-read the section on pointers - and pay attention to any warnings that the Compiler outputs. Otherwise you are really in for a world of frustration (not to mention the cryptic ARM exception codes…)

ciao, Dave

Actually, it is!

In a context like this, the “value” of a string literal is a pointer to the first character of the string.

since dataText is (probably accidentally) an array of pointers to char, dataText[0] is a pointer to a char - and so the assignment is valid!

[quote=“hade”]

adl_atSendResponse (ADL_AT_UNS, letter);

Check the documentation of adl_atSendResponse - is its 2nd parameter supposed to be a char :question:

that is exactly what i want. i have an array of data. each of them consist of a string. so maybe i better describe it like this :
i have 6 blocks of array : char* dataText[6].
each of the array (dataText[0],dataText[1],dataText[2],…,dataText[5]) is filled with a string data.
dataText[0]=“this is 1st”;
dataText[1]=“this is 2nd”;
dataText[2]=“this is 3rd”;
dataText[3]=“this is 4th”;
dataText[4]=“this is 5th”;
dataText[5]=“this is 6th”;
because a string is also an array of char so dataText will be the same as array of array of char.
And i tested it first to get the 9th character from the array using the 2 steps array. so if i wrote the code down like this :
char x = dataText[0][8];
printf(x);
it will show an output “1”.

yep that’s where i went wrong. so i changed my test method.

and by the way the code has worked. i have managed to get and send the character one at a time to the serial port in fcm data mode. but another problem occured. when i tried to send some length of data to UART1, only a certain length of the data was sent. i tried to send 300 of ‘0x00’ hexa data using a loop. but what i received was only 59 hex data. and it is always same when i tried to change either the data length or the data that i sent. why can’t i send a full length of hex data using loop method?
Thank you for the quick reply. You are all a really big help for me.

best regards,
Hade

Are you checking the return value from adl_fcmSendData each time you send a character…?

Nope. i didn’t checked the return value. Maybe that’s the source of my problem then. i should check it then. I’ll let you know after i checked it. Thank you so much Awneil and Davidc. :smiley:

Best regards,
Hade

return values are provided precisely so that you can confirm whether or not the call worked - and, if it didn’t work, they give the reason for the failure.

It is folly to ignore return values!
Again, this is general good programming practice - nothing specifically to do with Wavecom or Open-AT

Hi, i’ve checked my return value. and the result is ADL_FCM_RET_ERR_WAIT_RESUME. i suppose i must wait for the ADL_FCM_EVENT_RESUME to continue sending my data. i have tried it and yes after a small period of time i could send the rest of the data. but can i just release the credit every time i have send a data so i can avoid the ADL_FCM_RET_ERR_WAIT_RESUME event? because i see that is a function to release the credit. but it was not worked. this is the trace of FCM flow that i get. i don’t understand but i think it has something to do with the credit that was used.

Trace		5	C4>VU -1=59 1b                          // this is the start of sending process
Trace		5	VU>C4 +1=06                              // i made the code so after i send a data, i automatically release 1 credit
Trace		5	C4>VU -1=58 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=57 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=56 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=55 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=54 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=53 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=52 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=51 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=50 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=49 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=48 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=47 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=46 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=45 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=44 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=43 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=42 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=41 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=40 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=39 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=38 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=37 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=36 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=35 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=34 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=33 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=32 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=31 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=30 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=29 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=28 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=27 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=26 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=25 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=24 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=23 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=22 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=21 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=20 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=19 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=18 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=17 1b
Trace		5	VU>C4 +1=06
Trace		5	C4>VU -1=16 1b                            //this is the last data that was sent before the credit run out.
Trace		5	VU>C4 +1=06
Trace		5	C4>VU +1=17
Trace		5	C4>VU +1=18
Trace		5	C4>VU +1=19
Trace		5	C4>VU +1=20
Trace		5	C4>VU +1=21
Trace		5	C4>VU +1=22
Trace		5	C4>VU +1=23
Trace		5	C4>VU +1=24
Trace		5	C4>VU +1=25
Trace		5	C4>VU +1=26
Trace		5	C4>VU +1=27
Trace		5	C4>VU +1=28
Trace		5	C4>VU +1=29
Trace		5	C4>VU +1=30
Trace		5	C4>VU +1=31
Trace		5	C4>VU +1=32
Trace		5	C4>VU +1=33
Trace		5	C4>VU +1=34
Trace		5	C4>VU +1=35
Trace		5	C4>VU +1=36
Trace		5	C4>VU +1=37
Trace		5	C4>VU +1=38
Trace		5	C4>VU +1=39
Trace		5	C4>VU +1=40
Trace		5	C4>VU +1=41
Trace		5	C4>VU +1=42
Trace		5	C4>VU +1=43
Trace		5	C4>VU +1=44
Trace		5	C4>VU +1=45
Trace		5	C4>VU +1=46
Trace		5	C4>VU +1=47
Trace		5	C4>VU +1=48
Trace		5	C4>VU +1=49
Trace		5	C4>VU +1=50
Trace		5	C4>VU +1=51
Trace		5	C4>VU +1=52
Trace		5	C4>VU +1=53
Trace		5	C4>VU +1=54
Trace		5	C4>VU +1=55
Trace		5	C4>VU +1=56
Trace		5	C4>VU +1=57
Trace		5	C4>VU +1=58
Trace		5	C4>VU +1=59
Trace		5	C4>VU +1=60              //this is the size of the credit that i could use

i am pretty cpnfused with this.

could someone point me the right direction?

Best regards,
Hade

Think about it: serial data transmission is really slow relative to the speed of the processor.

Therefore your code can fill the output buffer far quicker the the UART can empty it.

Therefore, sooner or later, the buffer will get full. At that point, you have to stop trying to put more data into the buffer - or it will just be lost!

Again, this is common to all serial data applications; Wavecom use their strange “Credit” term, but the principle is the same…

Yes i could send a full length of data now. but is there some way to wait for the buffer to be cleared first then sending the next data? and what is the function of adl_fcmReleaseCredits, i mean what it is used for?

Yes - the ADL_FCM_EVENT_MEM_RELEASE indicates when some space has become available.

One way to proceed would be:

  1. Call adl_fcmSendData until you get a WAIT_RESUME result (if you don’t get WAIT_RESUME before you’ve sent everything, then you’re done)
  2. Wait until you get a MEM_RELEASE event - this indicates that you can call adl_fcmSendData again to send some more data
  3. etc, til you’re done.

You will need to implement a State Machine to handle this…

I’ve tried your method. And it worked. I am now able to send 200 uniform hex data. what i do is exaclty as you said that if i received the WAIT RESUME then i return the last number of data that i sent and wait for the RESUME event. Then i continue sending the data from the previously sent number in the RESUME event.

But what i need is to send a single hex data each time i call the FCM send data. because the data’s structure is different for each situation and condition. so i need to be able to send a a custom data one at a time.

Is there some way that i could make my application to wait or freeze after i send a single hex data, and wait for the MEM_RELEASE event? after that Then the application should continue after i received the event. so what’s in my mind is like this:

  • i made a function called sendFcmH( u8 data) which will be called each time i want to send a single Hex.
  • Inside the function i inserted the adl_FcmSendData and a ‘wait for MEM_RELEASE’ function.
    So Whenever i called the sendDataH(), the function will send the hex and wait for the MEM_RELEASE before continuing the application.

is it possible to do that in my application?

Best Regards,
Hade