Difference between revisions of "WICE RP How-To"
Line 130: | Line 130: | ||
To set up the communication between the RP module and the signal broker, the example program calls a function called <code>setup_pubsub_connection()</code> after parsing the command line parameters: | To set up the communication between the RP module and the signal broker, the example program calls a function called <code>setup_pubsub_connection()</code> after parsing the command line parameters: | ||
<code> | <code> | ||
pubsub_socket = setup_pubsub_connection(ip_addr, port_num); | pubsub_socket = setup_pubsub_connection(ip_addr, port_num); | ||
if(pubsub_socket<0) { | if(pubsub_socket<0) { | ||
Line 144: | Line 144: | ||
Note that the separator character has to be space, and the line terminated with Carriage Return + Line Feed (or optionally only Line Feed). | Note that the separator character has to be space, and the line terminated with Carriage Return + Line Feed (or optionally only Line Feed). | ||
<code> | <code> | ||
sprintf(str, "subscribe %s %s\n", RPEX_SIGNAL1, RPEX_SIGNAL2); | sprintf(str, "subscribe %s %s\n", RPEX_SIGNAL1, RPEX_SIGNAL2); | ||
n = send(pubsub_socket, str, strlen(str), 0); | n = send(pubsub_socket, str, strlen(str), 0); |
Revision as of 09:28, 25 May 2018
Getting Started with WICE Rapid Prototyping
To get started developing an RP component to be run on a WICE WCU you need the following:
- A toolchain for building executable programs on the target WCU platform
- A set of libraries providing APIs to the WCU hardware platform resources (e.g. CAN, diagnostics, logging, etc)
- WICE Portal access to configure the RP module for one or more WCUs
Software Development Toolchain
The development toolchain is typically installed on a desktop Linux system and then executables are built by cross-compilation. The following WCU platform architectures are supported:
- Host Mobility MX-4: ARM Cortex A9 or Cortex A5 processor, 32 bit
- Fältcom Committo: ARM 926EJ-S processor, 32 bit
- Actia Platform: MIPS processor, 32 bit
All toolchains are gcc-based. The MX-4 toolchain is availble here: http://releases.linaro.org/13.09/components/toolchain/gcc-linaro/4.7
WICE RP development API libraries
The following libraries are available:
- Canwrapper CAN library
- Debug logging library
- Timers and utilities library
- Tactalib Diagnostics library
- OBD II library
The development libraries are available here: http://www.alkit.se/rp/libs/
Building and executing the RP program
The binary file resulting from compiling the program for the target WCU platform is transferred to one or more in-vehicle WCUs using the WICE Portal. The binary will be executed when the WCU boots, and will be terminated when the WCU shuts down.
When executed, an number of command line arguments are given to the RP binary, as follows:
-vin <VIN number> -settings <filename> -logfile <filename>
The -vin
parameter supplies the Vehicle Identification Number of the vehicle the WCU is installed in.
The -settings
parameter supplies the path to a configuration file the user can supply through the WICE portal.
The -logfile
parameter supplies the path to a debug log file which will be uploaded to WICE portal when the RP module exits.
To get access to the information supplied on the command line at star-upt, the RP program must parse the command line.
A simple example RP program
The example code rpex.c
illustrates how to write a small program that can be executed as an RP module on the WICE in-vehicle WCU platform.
The example shows how to read a configuration file supplied on the command line, to write a CAN diagnostic request on a CAN bus and read a diagnostic reply, and to log data to a log file that will be uploaded to the WICE Portal.
The full source code of rpex is available here.
The first thing the example program does is to parse the command line parameters:
ret = parse_options(argc, argv);
if (ret != 1) {
return EXIT_FAILURE;
}
The parse_options
function sets the variables settings_filename
, log_filename
and vin
to the strings supplied on the command line.
Next, debug output is enabled, and the output filename is set to log_filename
, as specified on the command line. This ensures that the log file will be uploaded to the WICE Portal when rpex exits.
The debug_enable
and debug_msg
functions are defined in the alkit-debug
development library.
if (log_filename != NULL ) {
debug_enable(log_filename);
}
debug_msg(1, "rpex version is %s\n", RPEX_VERSION_STRING);
Then, after some more log output, the settings file is read:
if(settings_filename)
read_settings(settings_filename);
The settings file is the main way (except for the command line parameters) to provide input to the RP program. It can contain any type of input data needed by the program. In the example, rpex only reads text from the settings file and prints it to the output logfile.
The program is now ready to do its main work,in this case to send a diagnostic request on a CAN bus, and read a response. This is done using the alkit-canwrapper
library.
The following code block shows how to set up the CAN interface, prepare a CAN frame for transmission, set up a CAN filter matching the expected response, and then send the CAN frame.
// Initialize CAN interface
ret = init_can(canbus, DEFAULT_CAN_DEVICE);
can_device_fd = get_can_fd(canbus);
// Set up CAN filter
install_CAN_filter(canbus, 0, CAN_FILTER_TYPE_PASS, can_filter_id, can_filter_mask);
// Prepare CAN frame for request
memset(&req_frame, 0, sizeof(candata_t));
req_frame.id = ecu_id;
req_frame.bus_nr = canbus;
req_frame.frame_type = CAN_FRAME_11_BIT;
memset(req_frame.databytes, 0, 8);
req_frame.databytes[0] = 0x02; // SingleFrame, length = 2
req_frame.databytes[1] = 0x10; // Service 10
req_frame.databytes[2] = 0x01; // Default Diagnostic Session
req_frame.databyte_count = 8; // With padding
// Send CAN frame
debug_msg(1, "Sending diagnostic request on CAN bus %d...\n", canbus);
n = write_can(canbus, &req_frame, &t);
if(n<0) {
debug_msg(1, "Error writing CAN frame\n");
return -1;
}
The following code block shows how to read a response CAN frame.
// Read CAN response
FD_ZERO(&readfds);
FD_SET(can_device_fd, &readfds);
timeout.tv_sec = 0;
timeout.tv_usec = 200000; // 200 ms
ready = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
if (ready > 0) {
ret = read_can(canbus, &resp_frame);
if (ret == CAN_STATUS_OK) {
// Read successful
handle_can_frame(&resp_frame);
} else {
debug_msg(1, "Error reading CAN frame\n");
}
} else {
debug_msg(1, "No response.\n");
}
The function handle_can_frame
which is called when a frame is read simply logs the CAN identifier and payload to the logfile.
Using the high-level API for reading in-vehicle signals
To avoid the intricacies of reading CAN or FlexRay signals directly from the device, having to parse and interpret the signals, there is a high-level socket based API for reading in-vehicle and WICE-internal signals. The API is based on a publish/subscribe model, wherein the RP client subscribes to signals by name, and periodically gets signal values for the selected set of signals. The communication between the RP client and the WICE signal broker component is done over a socket.
The example code rpex-pubsub.c
illustrates how to use the publish/subscribe API. The full source code is available here.
To set up the communication between the RP module and the signal broker, the example program calls a function called setup_pubsub_connection()
after parsing the command line parameters:
pubsub_socket = setup_pubsub_connection(ip_addr, port_num);
if(pubsub_socket<0) {
debug_msg(1, "Pubsub connection failed\n");
exit(-1);
}
The setup_pubsub_connection()
function sets up a TCP socket to use for the communication.
To this socket, a subscribe command is sent with a list of names of the signals to subscribe to. The syntax of the subscribe command is as follows:
subscribe <signal name 1> <signal name 2> ...<signal name n><CRLF>
Note that the separator character has to be space, and the line terminated with Carriage Return + Line Feed (or optionally only Line Feed).
sprintf(str, "subscribe %s %s\n", RPEX_SIGNAL1, RPEX_SIGNAL2);
n = send(pubsub_socket, str, strlen(str), 0);
if(n <= 0) {
debug_msg(1, "Error subscribing to signals\n");
exit(-1);
}
Once the signals have been subscribed, the signal broker will send the signal values on the socket, to be read by the RP program, with the following syntax:
<signal name> value<CRLF>
The following code segment show an example of how to do this.
while(count < 100) {
FD_ZERO(&readfds);
FD_SET(pubsub_socket, &readfds);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
ready = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
if (ready > 0) {
n = read_line(pubsub_socket, &buf);
if (n > 0) {
// Read successful
handle_signal(buf);
free(buf);
count++;
} else {
debug_msg(1, "Error reading signal\n");
break;
}
}
}