When it comes to special solutions, it might often be desireable to extend emBASIC by custom written functions. This can easily be done if you are proficient in the C language and have access to the development CD for the underlying operating system - mCAT. emBASIC is prepared for C plug-ins that can be used for demanding regulator functions, exotic mathematics, access to specialized hardware etc. mCAT's extension mechanism is called Shared Library or ShLib. You can write such a ShLib to put all your extension functions into, then compile and download it to the target flash. With the next reset, emBASIC scans memory to find your ShLib and immediately presents your custom functions just as if they were built-in system functions. Writing a ShLib to extend emBASIC requires that you obey some guidelines such that emBASIC knows where to find the function prototype and the code and how to transfer the arguments. This will walk you through an example of two simple functions, one calculating
the length of a string using StrLen, a built-in function of the operating
system, and the other to return the square of an integer argument. lgth = STRLEN("emBASIC is now even
more powerful!") Start by creating a working directory for the project in your ..\mcat.2xx\cc source directory, lets assume it's ..\mcat.210\cc\embasext. Edit an mCAT target file to tell the system where to store your extension and name it like the directory: embasext.trg. If you have other system level extensions, you'll know where to store it, if not, the addresses 0x900000 in Flash-EPROM and 0x402000 in RAM used in this example are fairly safe places. A length of 0x1000 or 4K will certainly do for some standard functions. Our first two functions don't need any RAM, so it's ok to use any address for the RAM, the third uses a few bytes. To find out about available RAM, look at the "Memory block" section of emBASICs startup message: Everything between 402000 and the first value given there is quite safe. Next create a file and call it module.c. You also can name it after your grandfathers dog if you prefer, just not the same as the project, as a file named like the project (i.e. embasext.c) will be created by the ShLib utility MIC. In the text, start with including from the current directory embasic.h (declaring the emBASIC datatype definitions for parameter passing and the structure of the function argument prototypes), common.h and wrapper.h generated by the MIC tool as explained later. Further, include vtype.h and io.h from the standard include directory. Now the easy part: Writing the function that is called when the emBASIC expression containing our function is evaluated. To keep the sample concise we used an mCAT library function for the first and omitted any range checking on the second function. int StrLen(char *st)
static const emb_arg_proto_t strlen_arg[1] = { The following prototype structures have to be created for emBASIC's method table. emBASIC reads this table on startup and adds references to your C functions from this table to its parsing subsystem. The structure exfun_t defined in embasic.h consists of:
This is how it looks for our example: static const embfunc_t T[] = { As can be seen, the last entry is required to be a NULL entry. Finally, specify the ShLib entry function that returns a pointer to our method table "T": void* SYS_FDECL _emBASextGetTable() { Save module.c. Now edit the "Library Definition File" we named emBASext.ldf for our example. Only set the LIBID and VERSION, the NAME that gets copied into the libraries IMD. LIBID emBASext ARG NAME=Sample/emBASext AINCLUDE=.
CINCLUDE=. The LIBDEF lists all the functions we want to create. Start with the only required function GetTable that is used by emBASIC as an entry function to find our table LIBDEF emBASext # Mandatory entry
for emBASIC: GetTable If you only want to call the functions you create here from emBASIC, you are done with the ldf file and can skip to the MAKEFILE. However, if you want to use the functions from other C-tasks under mCAT, you have to make them accessible with more LIBDEFs. Library definitions can be grouped into families of similar functions. The family name is a prefix to the functions. In our example above the function "GetTable" of the emBASext family gets finally called as emBASextGetTable(). Hence we group our own functions into string and math and declare our functions StrLen and MathSqrInt as follows: LIBDEF Str It's a good practice to leave some space for later extensions. Now your functions can be called from other mCAT tasks as ShLib calls, too. As the last step, configure the MAKEFILE
for this project: PROJECT = embasext TARGET = embasext OBJFILES = $(PROJECT).rel wrapper.rel module.rel
Open a COMMAND window from your project directory and type vmake -r RESET your target controller and emBASIC should start up with the commands integrated. To find out, get the Shell on either AW or a terminal and !EXIT to immediate mode. Then enter !show shlibs: main# exit SHARED LIBRARIES: And you can now use the functions just as if they were built in. If the !Show shlibs command doesn't show anything, check the download memory. Enter BYE in immediate mode to leave emBASIC to SYSMON, then enter dump <addr> . If you don't see something starting AA 55 and showing the name you assigned to ARG NAME= in the .ldf then check the download. If this looks o.k. then you got to compare your C and ldf files to our sample to find out. Here's a ZIP of the project. 2+>dump 900000 |