Hosted App Developer Guide
Overview
The figure below gives an overview of the software architecture for hosting an application in the LMU 32-bit platform. HostedApp will be referred to in this document as 'HA'. The HostedApp and the LMU Application are separate binaries that are built and loaded independent of each other.
All the LMU APIs to the HA start with 'LMU_ '.
All the HA APIs called by the LMU start with 'HA_'.
Control Flow Model between LMU and HostedApp:
HostedApp Development
Resources Available
RAM Memory
A RAM space of 32K (or 40K) bytes is allocated for the HA. The Sample HostedApp project divides this allocation into 2K Bytes of "Uninitialized HA RAM" and the reminder as "General HA RAM". The HostedApp developer can change this distribution based on the requirements of the HostedApp, but the total RAM allocated for HA cannot exceed 32K (or 40K) Bytes. See the Memory Maps in Appendix A.
General RAM
The General RAM space is where most of the HA static/global variables are located. The Sample HostedApp project allocates 30K Bytes of General RAM for HA on F205 processors (HostedApp V1 - V4) and 40K on L4A6 processors (HostedApp V5 & V6).
Uninitialized RAM
The variables located in the "Uninitialized RAM" area are not initialized when the LMU starts up. The HA can use this area (2K Bytes in Sample HostedApp project) to store its data that will change often but is required to persist in situations (listed below) when the LMU goes through a software reset.
- Wakeup from Sleep
- Application Restart
- OTA Download Restart
- Factory Defaults
The HA is responsible for initializing variables in this area on appropriate boot conditions. The function HA_Init() implemented by HA is called each time the processor resets. This function provides the reason for LMU reset, Boot Reason. The HA should use the Boot Reason to determine which variables to initialize. Except for waking up from sleep where state information may be required to persist, all other boot conditions most likely will require initialization of the variables in the uninitialized RAM area. This decision is driven by HA requirements.
In the Sample HostedApp project a separate C source file 'API\NoInitData.c' is provided for uninitialized variables. The HA should define all its uninitialized variables inside this file in a global scope.
Internal Program Memory Flash
A Program Flash space of at least 128K Bytes is allocated for the HostedApp.
Please refer to Appendix A for the current LMU Internal Program Flash memory mapping for particular devices.
External Serial Flash
The HostedApp is allocated space in the external serial flash on the LMU. The amount of space and erase block size is dependent on the hosting LMU platform, currently a minimum of 1.25M Bytes. The available area and block size of the external serial flash memory is provided using APIs defined in section 'External Flash Memory Access' later in this document.
HostedApp Development Process
A Sample HostedApp project is provided that contains a framework and all the required settings for the development of the HostedApp.
Basic HA Development
The HostedApp is a separate Keil uVision project. It has place holders for HA API functions. The HA developer adds all the HA code to this project and builds the binary "HostedApp.bin". The AT command "ATHADNLD" can used on the LMU to "sideload" the HostedApp into the LMU, or the HostedApp can be uploaded to PULS and scheduled for download the next time the device checks in. The HA loading process creates a HA security signature on the LMU and resets the LMU. The LMU validates this signature at start-up and enables the calls between HA and LMU.
HA Framework Layer
In the HostedApp project there are other files that provide the framework for accessing LMU API functions and for allowing LMU to access HA API functions.
These files are located in a separate source group which the HostedApp developer does not have to worry about. The LMU firmware also has its side of the HostedApp framework added to it.
Quick Start
Compiler
Keil (http://www.keil.com) produces cross-compilers for the CPUs used in LMU devices. A free/Lite version is available that can compile small projects of under 32Kb of code. If licensing the compiler, get the MDK-Essential version. (The MDK-Plus and MDK-Professional versions have extra components and middleware that the LMU products don't use so these versions aren't necessary.)
To install, go to http://www.keil.com > Download > Product Downloads > MDK-Arm, fill in the form, then download MDKnnn.EXE and run it. After installation, let the Pack Installer automatically install any needed components, then close the Pack Installer.
Sample Apps
CalAmp provides a sample HostedApp that can be used as a template for HostedApp development. Contact your CalAmp Support Representative to obtain the latest version of the sample HostedApp package.
The sample HostedApp contains configurations to build apps that run on either LMU-4230 (HostedApp types "V1" through "V4", based on the STM32F205 CPU family) or LMU-3640 ("V5" and "V6", based on the STM32L4A6 CPU family) family devices. See Appendix A for which LMU AppIDs apply to which HostedApp type.
Download & unpack the Sample_HostedApp zip file.
For LMU-4230 development:
- First time only, double-click on HostedApp_4230.uvproj. Chose Install Legacy Support …, download & install in suggested packages, and close the Pack Installer when complete.
- Subsequently, double-click on HostedApp_4230.uvprojx.
For LMU-3640 development:
- First time only, double-click HostedApp_3640.uvprojx. Allow Pack Installer to install any needed components and close the Pack Installer when complete 1
- Subsequently, double-click on HostedApp_3640.uvprojx.
Choose HostedApp type from toolbar dropdown according to the target device. (4230 offers types V1 through V4; choose "HostedApp" for HostedApp type V1. 3640 offers types V5 & V6.)
Project > Build [F7] or Rebuild all target files.
Note: If no variables are defined in the NoInitData.c file, the linker may produce "… warning: L6314W: No section matches pattern NoInitData.o(ZI)". This warning can be safely ignored.
On successful compilation & link, the resulting binary file is available at output\HostedAppVx\HostedAppVx.bin.
Loading onto LMU
A compiled HostedApp binary can be either "sideloaded" over a serial connection directly to the LMU, or can be uploaded to PULS for download the next time that the device checks in.
Sideloading
Requires a terminal program that supports "large file" YModem transfers.
While connected to the LMU's serial debug port, issue the command "ATHADNLD". The HostedApp area of flash memory will be erased and a YModem receive (displays "CCCC…") will be started. Transmit the HostedApp .bin file. When the transfer is complete, the LMU will reboot itself. Output from the HostedApp will display in the serial debug log with the prefix "HA:".
Loading via PULS
Managing HostedApps through PULS requires that your login has the appropriate permissions. Check with your CalAmp Support Representative.
In PULS, Devices > Hosted Apps > Hosted App Files displays the apps previously uploaded:
Choose DEVICES > Hosted App Files > ADD HA FILE or DEVICES > Hosted Apps > ADD HA to upload a new HostedApp:
The following information is requested:
Hosted App AppID: HA AppIDs 250 through 254 are reserved for customer-written HostedApps. The value corresponds to the value returned by the HA_getID() function in the app.
File Type: "Hosted App Firmware File" (V1) thorough "Hosted App V6 Firmware File".
File: The HostedAppVx.bin file.
Version: A string to be displayed on the Hosted App Files page. (Note: no spaces are allowed in this string.)
Customer: The account(s) to which the HostedApp file will visible.
To schedule a HostedApp for one or more devices:
For a single device: Enter the ESN and View Device. On compatible devices, a Hosted App tab is visible:
For multiple devices: Use DEVICES > Hosted Apps to SELECT and display all devices in a Customer / Group. Check the devices to be updated and click HOSTED APP to move to the page to select the desired HostedApp file and then ASSIGN.
Basic HostedApp Routines
HA Initialization
void HA\_Init(const unsigned char bootReason)
The LMU calls this API (implemented by the HA) from its initialization routine once after reset to allow HA to initialize prior to operations. The HA is required to initialize all its static variables in this routine. This API also passes the Boot Reason for calling the Initialization routine. The Boot Reason can be one of the following values.
Value | Boot Reason |
---|---|
0 | Cold |
1 | Factory |
2 | Over-The-Air Download |
3 | Radio Power Up |
4 | Wakeup from I/O Activity |
5 | Wakeup from Timer Expiry |
6 | Wakeup from Comm Activity |
7 | Application Restart |
8 | N/A (Wakeup from TTU Hibernate mode) |
9 | N/A (Wakeup from TTU Standby mode) |
10 | Wakeup from Low-Battery Sleep |
11 | HostedApp Over-The-Air Download |
12 | Wakeup from OBD/JPOD Trigger Activity |
13 | Wakeup from Deep Sleep |
14 | Wakeup from VLU Activity |
15 | Limited Wakeup on OBD Motion Detect |
Note: When the unit wakes up from sleep a reset is done and as a result this function gets called again from the LMU initialization routine.
HA Main Routine
HA_Main(void)
The LMU calls this API (implemented by the HA) each time the LMU passes through its background loop. It is called repeatedly after the one time call to HA_Init(). HA_Main() shall keep its processing time to a minimum and should return as soon as possible. No blocking calls or infinite loops are allowed in this routine.
Debug API
void LMU_postDebug(char const *fmt, ...)
This API supports printf()
style format specifiers and outputs strings to the debug port. When displayed in the debug port the HA debug string is prefixed by a timestamp and the string "HA:", an example below.
Example:
app[17:30:18] HA: This is a test debug string from HostedApp.
Device Identification & Status
const char *HA_getID(unsigned char *pAppID)
This API (implemented by the HA) provides the LMU with the Application ID in the variable pointed to by pAppID and returns a pointer to a version string (16-character including NUL. These values used by the ATI0 command and in IDReports to PULS to manage Over-The-Air HostedApp updates.
Note: PULS may refuse to upload the app file if the version string contains embedded spaces so using underscores '_' instead of spaces is recommended).
Note: HostedApp developers should contact CalAmp Engineering, via your CalAmp Support Representative) to obtain a unique Application ID assigned for their application. For customers that want to assign their own App IDs, the values 250 through 254 are available.
int HA_GetStatusString(char *statusString, unsigned short len)
This API (implemented by the HostedApp) populates statusString with human-readable status (NUL terminated) that is returned by the ATIH and AT$APP HA? commands. The string may include <CR><LF> for multiline status. At most len characters are put in statusString including the NUL terminator. Returns true if status is populated.
void LMU_getDevSer(char *devSerStr)
Fills the 11-byte array devSerStr with the 10-digit ESN plus a terminating NUL.
HA AT commands
The 'HA AT commands' provide a method to pass information to the HostedApp from the AT command interface.
AT$APP HAMSG word
AT$APP HAMSG "words …"
If the tail of the command is unquoted, the first word (up to a space or the end of line) will be forced to uppercase and passed to the HostedApp. If the tail of the command is quoted, the full string, minus the quotes but with a NUL terminator appended, will be passed to the HostedApp via the HA_MsgFromAT() function.
The size of the AT$APP command string cannot exceed 120.
void HA_MsgFromAT(const char *buffer, unsigned short len)
LMU calls this API function to pass the contents of a received AT$APP HAMSG. 'buffer' points to the passed NUL terminated string; 'len' is the string length including the NUL terminator.
LMU Services for the HostedApp
HA Configuration Parameters
The following configuration parameters are available for the exclusive use of the HostedApp.
Parameter ID | Type | No. of indexes |
---|---|---|
2688 | 8-bit | 32 |
2689 | 16-bit | 16 |
2690 | 32-bit | 16 |
2691 | Short String (16 characters max) | 16 |
2692 | Long String (64 characters max) | 8 |
Parameter Read
void * LMU_readHAParam(unsigned short paramID, unsigned char paramIndex)
This API takes the parameter ID and index and returns a void pointer to the parameter value. For error conditions such as invalid Parameter ID, invalid index etc. this API returns a NULL pointer.
Parameter Write
Bool LMU_writeHAParam(unsigned char *PBuf, unsigned char PBufLen)
This API is used to set the value of a configuration parameter stored by the LMU application. For most AppIDs, the ability to modify parameter values via this call is limited to the specific Parameter IDs 265, 1036, 1037 and 1052.
The API takes two input parameters: a pointer to a buffer containing the config parameter info, and buffer length. Return value is TRUE on successfully setting the configuration parameter and FALSE otherwise.
The buffer contents must have the following format:
Parameter ID (2 bytes) | Parameter Index (1 byte) | Mask | Value |
---|
The sizes of the fields Mask and Value depend on Parameter ID (see https://puls.calamp.com/wiki/Parameters for details). If the parameter doesn't require a mask than the Mask field is omitted. All fields are big endian.
Examples:
The equivalent of at$app param 265,11,540 (set timer 11 to 9 minutes) will translate into the following buffer contents:
01 09 0B 00 00 02 1C
(Note: parameter 265 does not take on a mask, and the value is a 32-bit number).
The equivalent of at$app param 1037,0,2147483653,2147483649 (set PEG Enables 0 and 31 and clear PEG Enable 2) will translate into the following buffer contents:
04 0D 00 80 00 00 05 80 00 00 01
(Note: parameter 1037 has only one index and requires a 32-bit mask and a 32-bit value).
PEG Script Support for HA
HA PEG Trigger
void LMU_postHAPEGTrigger(unsigned char triggerModifier)
This API posts the PEG Trigger 'Hosted App' (#70) with the Trigger Modifier from the parameter 'triggerModifier'. HA can call this API to provide any special notification to the PEG script.
HA PEG Condition
Bool HA_PEGCondition(unsigned char condModifier)
This API function should be implemented by the HA. The LMU will call this API when a PEG Script line contains the 'Hosted App Condition Equal' PEG Condition (#56) with the specified Condition Modifier. The function returns TRUE or FALSE to the PEG Script.
HA PEG Action
void HA_PEGAction(unsigned char actionModifier)
'Notify Hosted App' PEG Action (#121) is an Action initiated by the PEG Script with the specified Action Modifier to have the HA do a specific action or send a special notification to the HA. HA should implement this API.
Accumulators
Read
unsigned int LMU_getAccumValue(unsigned char accumIndex)
This API returns the value in the LMU accumulator pointed to by 'accumIndex'.
Write
void LMU_putAccumValue(unsigned char accumIndex, unsigned int accumValue)
This API writes 'accumValue' into the LMU accumulator pointed to by 'accumIndex'.
Get Input Lines Status
unsigned short LMU_getInLines(void)
This API returns the status of all input enabled lines.
Get Output Lines Status
unsigned short LMU_getOutputState(void)
This API returns the status of all output enabled lines.
ADC Channels
unsigned short LMU_getADCmV(unsigned char channelID)
This API returns the ADC value of 'channel ID in millivolts. If the channel is not valid it returns '0'.
Get Comm Jamming State
Bool LMU_getComm0Jamming(void)
This API returns current state of Radio Jamming detection for Comm Route 0.
HA Sleep Readiness
signed char HA_State(void)
LMU calls this API function prior to sleep to get HA's go ahead for sleep. If the State returned is STATE_READY (see table below) it goes ahead and initiates the sleep process. If the State returned is STATE_NOT_READY it postpones the sleep process and checks back after 8 seconds.
State | Value | Description |
---|---|---|
STATE_NOT_READY | 0 | HA is busy and cannot sleep at this time |
STATE_READY | 1 | HA is ready for sleep |
Application Messages & UDP Socket Interface
There are 2 ways to send and receive UDP data through the LMU radio interface.
LMDirect Application Message
The LMDirect Application Message serves as a container for HA messages. The HA should use Application Message IDs 200 and above for this service.
signed char LMU_sendLMDAppMsg(unsigned short appMsgID, const unsigned char *payload, unsigned short len, Bool bmsgACKed, unsigned char commRoute)
This API is used to send HA data in an LMDirect Application Message.
API Parameters
appMsgID
: value 200 or abovepayload
: pointer to the data buffer to sendlen
: length of the buffer to sendbmsgACKed
: indicates if the message needs to be acknowledged
TRUE – acknowledged LMDirect message
FALSE – unacknowledged LMDirect message
commRoute
: selects the communication route
0 - selects the default radio, inbound server index 0 and Log ID 0
1 - selects the alternate radio as defined in S-Register 150, inbound server index 1.
Note: To use the alternate route the LMU should have been configured for Dual-Comm. Refer to the LMU Dual Comm Architecture document for further details.
API Return Values
A value greater than zero indicates success
void HA_RcvDataLMDAppMsg(unsigned short appMsgID, unsigned char *rcvBuf, unsigned short len, unsigned char commRoute)
Host Application should implement this API function. All data received with LMDirect Application Message IDs 200 or above will be passed into the Host Application through this API.
appMsgID
: The LMDirect Application Message ID that this message came withrcvBuf
: The pointer to the data received (contains only HA data - all LMDirect headers removed)len
: The length of HA data receivedcommRoute
: The communication route this message came from.
Raw UDP Socket
The Raw UDP socket provides HA the option to send and receive UDP data without any LMDirect headers.
Send Data
Bool LMU_UDPSendPkt(unsigned long address, unsigned short port, unsigned char *sndBuf, unsigned short len, unsigned char commRoute)
This API is used to send len
bytes from the buffer pointed to by sndBuf
to the destination IP address and port indicated by parameters address
and port
through the communication route commRoute
. The source port of the outgoing datagram will be the HA UDP Port so that HA_UDPRcvPkt()
can receive responses from servers that send back to the originator.
Returns TRUE for success, FALSE if any module involved in sending returned SOCKET_ERROR (bad socket, len too long, no route to host, etc.)
Receive Data
void HA_UDPRcvPkt(unsigned long address, unsigned short port, const unsigned char *rcvBuf, unsigned short len, unsigned char commRoute)
The HA UDP Port is configured using HA UDP Port LMU Configuration parameter (Parameter ID 2693). The LMU at start up initializes the HA UDP Socket and starts listening on the HA Port. It forwards any UDP data that comes into the HA Port to the HA through this API. The Source IP address and Source port and passed through parameters address
and port
along with the received data and length through parameters rcvBuf
and len
and commRoute
is the communication route this message came from.
Note: The Communication Route feature for the send and receive APIs is not yet supported and its value should be ignored. Support for Communication Route will be added in the future.
Current PEG Comm Route Selection
PEG maintains a current Comm Route selection for LMU Event Reports.
This is selected dynamically by a PEG Action. It will be useful to know what the PEG comm. Route is when specifying the Comm Route in the send API.
Note: The PEG Comm Route and the Comm Route specified in the send API are independent of each other; i.e. the send API will use whatever Comm Route is specified in the parameter irrespective of what PEG is set for.
unsigned char LMU_getPEGCommroute(void)
returns 0 or 1 indicating the current PEG Comm Route.
Communication Link Status
void LMU_getCommStatus(unsigned char commRoute, COMM_STAT *pCommStat)
This API function gets the status of the communication link for the communication route specified in parameter commRoute
and updates the COMM_STAT structure (see definition below) pointed to by the parameter pCommStat
.
typedef struct tagCOMM_STAT {
short rssi; // Signal Strength
BOOL bConnected; // Packet Session Active
BOOL bDataSrvc; // Data Service is available
BOOL bNetworkSrvc; // Network Service is available.
BOOL bRoaming; // TRUE if modem is roaming on a different network.
} COMM_STAT;
Serial Stream Interface
There are three serial streams available for the Host Application.
These streams can be mapped to the desired physical serial port with the required port settings using LMU Stream Configuration Parameters.
Open
int LMU_openHASerial(unsigned char streamID)
A Serial stream has be to be opened before any serial communication can be accomplished with it. This API opens the specified Host Application Serial stream ID (values 0, 1 or 2). A return value that is greater than 0 indicates that the operation is successful.
Send Bytes
int LMU_sendHASerial(unsigned char streamID, const unsigned char *buf, unsigned short len)
This API is used to send len
number of bytes from buffer pointed to by buf
to the stream ID specified. A return value that is greater than 0 indicates that the operation is successful.
Receive Byte
int LMU_rcvByteHASerial(unsigned char streamID,unsigned char *byte)
This API reads one byte from the stream specified and returns a non-zero value. If there is no data received from the stream it will return zero. Host Application should call this API periodically in its background process to ensure that it does not miss any bytes received from the stream. In order to receive all bytes the HA has to call this function repeatedly until it stops returning a value greater than zero.
Close
int LMU_closeHASerial(unsigned char streamID)
This API closes the specified Serial Stream.
HA Port
The HA Port or the 'Hosted Application port' is used by the HA to gain access to the Serial streams of the LMU such as NMEA Out and User Serial Streams. This is essentially a virtual serial port similar to the physical serial ports supported by the LMU. The stream that the HA would like to communicate with needs to be mapped to the 'HA port' using LMU Stream Configuration parameters.
Send
int LMU_sendHAPort(unsigned char *sndBuf, unsigned short len)
This API is used by the HA to pass data to the stream assigned to the HA port. len
number of bytes from buffer pointed to by sndBuf
are passed. The LMU stream configured to the HA port sees this as incoming data. A return value greater than '0' indicates that the operation is successful.
Receive
void HA_rcvDataHAPort(unsigned char *rcvBuf, unsigned short len)
This API function is implemented by the HA and is called by the LMU stream to which the HA port is assigned when the stream is sending data. rcvBuf
is the pointer to the data being passed and len
is the number of bytes being passed.
Send String to AT Interface
void LMU_UnsolicitedMsgToAT(const char *buffer, unsigned short len)
Note: This function is currently unimplemented.
Note: To allow the HostedApp to issue AT commands, connect the HAPort [Port 7] to one of the ATCmd-1 or ATCmd-2 Streams [Streams 15,16] and then use LMU_sendHAPort() to issue a command that begins with "AT" and ends with a carriage-return, for example: "ATS147=100\r". (Since the call is emulating a human typing in the command, only the \r carriage-return is needed.) Note that the AT command is executed asynchronously – the HA_Main() must relinquish control to the LMU to allow the LMU's ATCmd processor to execute the command and write the output to a buffer that later calls to HA_rcvDataHAPort() will consume.
External Flash Memory Access
The LMU does not have a file system and exposes raw APIs to the external SPI Flash Memory. The Flash routines are raw APIs and do not provide any wear levelling. The HostedApp is responsible for implementing any wear levelling or file system. Flash writes will work only when the area being written is in an erased state.
External Flash Details
The available Flash size and erase block size depend on the LMU platform type that the HostedApp is developed for.
unsigned int LMU_getExtFlashInfo(unsigned int *pBlockSize)
This API provides the erase block size in bytes in the variable pointed to by pBlockSize
and returns the size of flash space allocated for the HA in bytes.
Read
int LMU_extFlashRead(unsigned long addr_offset, char *buf, unsigned long size)
This function reads size
number of bytes from the flash address pointed to by addr_offset
into buf
, a buffer owned by the caller. The function returns the number of bytes successfully read. The valid values of the addr_offset
parameter range from 0 to size returned from calling the API LMU_getExtFlashInfo()
.
Erase
Bool LMU_extFlashErase(unsigned long addr_offset)
This function erases the flash at the address offset specified. The size of the area erased depends on the blocksize provided by LMU_getExtFlashInfo()
.
Note: The address indicated by addr_offset
parameter has to start on the correct boundary based on the blocksize provided by API LMU_getExtFlashInfo()
. Otherwise the erase will fail and this function will return FALSE.
Write
int LMU_extFlashWrite(unsigned long addr_offset, char *buf, unsigned long size)
This function writes size
number of bytes from buffer buf
to the flash address pointed to by addr_offset
. It returns the number of bytes successfully written. The valid values of the addr_offset
parameter range from 0 to size returned from calling the API LMU_getExtFlashInfo()
. If the area being written is not in an erased state this function will return -1.
File Download Support
The HA can receive files from PULS which can then be transferred to the HA's own external flash area, sent to an external device over a serial port, etc.
The kind of file sent by PULS is identified by a FileType value.
Identifying FileTypes
The HA advertises to PULS the file types that it can receive and the current version of those file types by providing extension strings that are added to each outgoing ID Report.
void HA_appendOTAExtStr(char *strExt)
This API (implemented by the HostedApp) appends the file types managed by the HA that need OTA download support in the following format to strExt
,<fileID1>,<fileID2>,...<fileIDn>
Example: To indicate that the HA needs OTA download support for Dev1 (Type 5) firmware, it will append the following.
,5
If no files require OTA download support, the HA should do nothing.
void HA_appendIDVerExtStr(char *strExt)
This API (implemented by the HostedApp) appends the file types managed by the HA and their version information in the following format to strExt
,<HA Filetype1><versionstring1>,<HA File type2>,<version string2>,..<HAfile Type n>,<VersionString-n>
Example: To append versions for file type 5 and file type 7.
,5,a.b.c,7,x.y.z
If there is no applicable version, do not specify a versionstring but include a comma character if there are other file types following it.
If no files are supported by the HA, the HA should do nothing.
Receiving Files
When the LMU has received a file into its OTA Download area, it interacts with the HA to process the file in the following steps:
- The LMU asks the HA how large a file of a particular file type it will accept.
- The LMU informs the HA that a file of file type & size has been received.
- The HA makes one or more calls to read the file from the OTA Download area and process it, for example, writing each buffer read to the HA's external flash area. (The file should contain version information so that the HA can report the new version in subsequent ID Reports.)
- When the OTA Download area has been fully processed, the HA informs the LMU that Download is complete.
unsigned long HA_getMaxFileLen(unsigned char fileType)
This API (implemented by the HostedApp) provides the LMU with the maximum length of the file that is supported by the HA for the given 'fileType'. This is required for the LMU Download module to erase the required amount of OTA file storage space before it downloads the file from PULS.
void HA_programFile(unsigned char fileType, unsigned long fileLen, char *strDevParam)
This API (implemented by the HostedApp) is called when a file for the HA has been downloaded into the Serial Flash and is available to be processed by the HA.
The parameter strDevParam
is currently an empty string and can be ignored.
int LMU_DNLD_File_Read(unsigned long addr_offset, unsigned char *buf, unsigned long size)
This function reads size
number of bytes from the OTA Download file storage area at the offset pointed to by addr_offset
into buf
, a buffer owned by the caller.
The function returns the number of bytes successfully read.
void LMU_DNLD_progFileStatUpd(unsigned char stateCode, unsigned char diagCode, Bool bSndIDRprt)
This function should be called when the HostedApp has completed processing the OTA Download file storage area.
stateCode
can be one of the two following values:
Value | Description |
---|---|
5 | Programming successful |
6 | Programming failed |
diagCode
provides extra information about the stateCode
, which is reported in PULS:
Value | Description |
---|---|
0 | None (when Programming was successful) |
1 | Invalid File length |
2 | Invalid File format |
5 | Flash Erase Failed |
10 | Flash Verify Failed |
11 | Flash Write Failed |
13 | Checksum Error |
14 | Version Incompatible |
bSndIDRprt
when TRUE/non-zero will queue the sending of an ID Report.
Location Data
void LMU_getGPSDataParsed(GPSData *pGPSData)
This API takes a pointer to the GPS data structure (see structure definition below) owned by the HA and populates the GPS data structure with the parsed GPS data based on the data that was last obtained from the GPS receiver.
typedef struct tagGPSData {
INT32 lat; // Decimal Degrees, Fixed Point, LSB = 1E-7 deg
INT32 lon; // Decimal Degrees, Fixed Point, LSB = 1E-7 deg
INT32 alt; // Altitude above Datum, LSB = 0.01 meter
UINT32 tof; // Time of Fix, UTC-Unix, 32-bit, 1-sec LSB
UINT32 udtime; // Current LMU System Time, UTC-Unix, 32-bit, 1-sec LSB
UINT32 tod; // time-of-day of fix from GPS Receiver
UINT32 spd\_cmps; // speed in centimeters per second
UINT16 speed; // speed in miles per hour
UINT16 heading;
UINT16 hdop;
UINT8 fixstatus; // Bitmapped –see below
UINT8 nsats; // No. of Satellites used in the Fix_ _UINT8 hpos\_acc; // 1-sigma (67%) Horizontal Pos._ _Accuracy estimate, LSB = 1 meter
UINT8 reserved; // Ignore
BOOL reserved; // Ignore
} GPSData;
fixstatus
: 8 bit (Bit mapped) Ignore the bits that are not defined
#define FIXSTAT_DIFF_FIX 0x02 // Differential Fix
#define FIXSTAT_INVALID_FIX 0x08
#define FIXSTAT_2D_FIX 0x10
#define FIXSTAT_INVALID_TIME 0x40
GeoZones
void HA_geoZoneEvent(GeoZoneData *pGeoZoneData)
This API is called when a GeoZone Entry or Exit event happens. The following information is provided through parameter pGeoZoneData
a pointer to the GeoZone structure.
Attribute | Size | Values/Description |
---|---|---|
Event | 8 bits | 0-Not Used, 1-Entry, 2-Exit, rest not defined |
Type | 8 bits | 0-Not Used, 1-Point Zone, 2-Polygon, 3-Route, rest not defined |
ID | 16 bits | Bits 0-7: ID, Bits 8-11: SuperGroup, Bits 13-15: Unused |
Range/Data | 16 bits | Range for Point Zones. Also may be used to communicate other information when the GeoZone Record area that is meant to store Range is used for storing other generic data |
typedef struct tagGeoZoneData {
unsigned char Event; // 0-Not Used, 1-Entry, 2-Exit, 3 and above – not defined
unsigned char Type; // Zone Type
// 0-Not Used,1-Point Zone,2-Polygon,3-Route, 4 and above- Not defined
unsigned short ID; // Includes ID and SuperGroup
// Bits 0-7 – ID;Bits 8- 11 – SuperGroup,
// Bits 13-15- Not used
unsigned short range_Data; // Range for Point Zones,
// also used to communicate other information when
// the GeoZone Record area that is meant to store Range
// is used for storing generic data other than Range
} GeoZoneData;
int LMU_getGeoZoneState(unsigned char GeoZoneId, unsigned char SuperGroup)
Returns TRUE if last location is currently inside the GeoZone specified by GeoZoneId
and SuperGroup
, else returns FALSE.
Time
Bool LMU_getTimeData(unsigned int *pSysTime, long *pLocalOffset, unsigned char *pTimeSource)
This API updates the variable pointed to by pointer pSysTime
with time in seconds since 1 Jan, 1970. The variable pointed to by pointer pLocaloffset
is updated with local time offset in seconds from GMT. A positive offset is East of Greenwich PST = -8hours). This API returns TRUE if the time is valid. This API also provides the source of time by updating the variable pointed by pTimeSource
with one of the following values.
Return Value | Time Source |
---|---|
0 | GPS (After 3D fix) |
1 | Real Time Clock |
2 | GPS (Prior to 3D fix) |
3 | Server |
4 | Cellular Network |
5 | No Time Source |
unsigned int LMU_getSysticks(void)
This function returns the milliseconds since cold boot or wakeup. Note that a 32-bit millisecond counter wraps every 49.7 days!
Ignition
Bool LMU_getVirtIgnState(void)
The LMU uses configurable de-bounce and delay timers and reports a virtual ignition input state that is protected from momentary changes in the ignition input. This API provides the state of the virtual Ignition input. It returns TRUE when virtual Ignition is ON and FALSE otherwise.
Read Vbus Configuration Parameter
void LMU_readVbusCfgParam(unsigned short paramID, unsigned char paramIndex)
This API is used to query the value of a VBus configuration parameter. To return the contents of the requested configuration parameter, the LMU calls the following API function:
void HA_readVbusCfgParamResp(const char *buffer, unsigned short len)
where buffer points to len bytes of binary parameter data.
Example:
If a JPOD2 configuration contains the line
5100,0,110022000020006000000000
then LMU_readVbusCfgParam(5100,0)
will return a pointer to the byte array below (with values shown in decimal), with len = 12:
{ 17, 0 , 34 , 0 , 0 , 32 , 0 , 96 , 0 , 0 , 0 , 0 }
If the call is unsuccessful, buffer will have a value of NULL and len will be 0.
Write Vbus Configuration Parameter
void LMU_writeVbusCfgParam(unsigned char *buffer, unsigned char len)
This API is used to set the value of a VBus configuration parameter. The data (pointed to by buffer
) is a NUL terminated ASCII string containing the parameter to be written to, parameter index, and parameter data separated by commas. The data is a sequence of decimal values also separated by commas (if more than one). If the data is a hex string, it is written as a sequence of decimal bytes. In the examples below, all three representations result in the same data being written into the specified parameter:
Example 1:
buffer: 5300,0,520012802
record in configuration file: 5300,0,1EFEC402
Serial AT command: at$app vbus param 5300,520012802
Example 2:
buffer: 5107,2,7,2,34,0,0,0,240,4,0,65,0,16
record in configuration file: 5107,2,070222000000F00400410010
Serial AT command: at$app vbus param 5107,2,7,2,34,0,0,0,240,4,0,65,0,16
To pass the response to a request to modify a VBus configuration parameter, the LMU calls the following API function:
void HA_writeVbusCfgParamResp(Bool success)
Request Vbus Data Group
void LMU_requestVbusDataGroup(unsigned char reportID)
This API is used to request a data group report from a VBus device. To pass the contents of the requested data report the LMU calls the following API function:
void HA_requestVbusDataGroupResp(const char *buffer, unsigned short len)
Vehicle Bus CAN frames raw access
CAN frames pass-through allows the HostedApp to request raw CAN frames and also to put raw frames onto the bus.
There is no knowledge in the API about anything other than CAN frames. Just the CAN address, address type, remote request bit, and up to 8 bytes of data are supported.
CAN Frame Structure
typedef struct tagCANFrame
{
unsigned long id;
unsigned char ide;
unsigned char rtr;
unsigned char dlc;
unsigned char data[8];
} CANFrame;
The above type definition is provided in the API header and defines the CAN frame structure used in the send and receive fudnctions in the API. There are five members in the CAN frame structure:
id
: The CAN address that identifies the node.ide
: Identifier extension. 0 for standard frames format (not supported), 1 for extended frame format. Must be 1 in this API.rtr
: Remote Transmission Request. 0 for data frames, 1 for remote request frames.dlc
: Data Length Code. Number of bytes of data (0-8 bytes).data
: 0-8 bytes of data. Length set by the dlc member.
Send
void LMU\_CANSendFrames(unsigned char ID, const void *canFrame, unsigned short count)
This API is used to send a message to a connected VBus device to place one or more CAN frames onto a specified CAN bus.
The API takes three input parameters: an identifier to specify which bus to send the frames on, a pointer to an array of CAN frames to be transmitted, and a count of the number of CAN frames in the array.
Note that frames should not be sent too frequently. Allowance must be made for other users of the vehicle bus. Frames sent less than 100ms after the previous frame will be discarded by the JPod‑II.
Receive
void HA_CANReceiveFrame(unsigned char ID, const CANFrame *canFrame)
This API function is implemented by the HA and is called by the LMU to pass the contents of a received CAN frame to the hosted application. The first parameter identifies the bus from which the CAN frame was received. The second parameter points to the received CAN frame.
The CAN frames received are those subscribed to by setting JPod-II configuration parameters 5300 – 5304. Refer to PULS Wiki > JPOD2 > JPOD2 Config Tutorial (tab).
Note that it is not possible to receive all the CAN frames because the CAN bus is too fast.
Memory Maps
Depending on features, per AppID, a device may have no HostedApp or space for 128K, 160K or 256K of HostedApp.
The best method to determine the correct HostedApp type for your device is to issue the following command:
ATIH
Flash Memory Map
RAM Memory Map
SPI Flash Memory Map
Note that the HA External Flash Memory API calls are all relative to the area reserved for HostedApp.
Footnotes
1 Seen in recent compiler releases (up to MDK531 at least), there appears to be a bug in the STM32L4A6VGYx support package, resulting in a E203: Undefined identifier - 'DoOptionByteLoading' error in the Build Output window. To work-around this, open C:\Users\<user>\AppData\Local\Arm\Packs\Keil\STM32L4xx_DFP\2.4.0\Keil.STM32L4xx_DFP.pdsc file, locate the string Device 'STM32L4A6VGYx' and in the <debugvars> … </debugvars> section above it, add the line
__var DoOptionByteLoading = 0;
Updated about 3 years ago