Introduction
Squish Coco generates the code execution measurement using streams and by default, the output of these streams is piped to a file on the file system. For embedded devices without a file system, this leads to problems. Squish Coco allows you to redirect the measurements stream via Custom IO Functions. In this article, we create a showcase with the common CAN Bus.
The Basic Setup
The Basic Setup of a CAN bus is a transceiver which handles the voltage on the wires and also a controller which saves incoming and outgoing frames into registers.
For this showcase we will connect a micro controller to a Linux system. This is achieved by connecting the Linux system via USB adapter to the CAN bus. The USB adapter integrates the controller and the transceiver. On the other side, we use a STM32 micro controller which has the CAN bus controller already integrated. Finally, we need a transceiver, which is achieved by connecting the micro controller to a Breakout board which contains the transceiver.
General flowcharts for the PC receiver and the micro controller
PC receiver
The main task of the PC receiver is to invoke the __coveragescanner_save()
function on the micro controller, receive the data and write it to files on the PC.
Micro controller
The normal process is running on the micro controller until the save message is received and the measurement data is sent.
Implementation of Custom IO Functions
When the micro controller receives the RECEIVESAVECOMMANDMESSAGEID
over CAN bus, the save is initialized.
status = HAL_CAN_Receive(&hcan, CAN_FIFO0, 100); if (status != HAL_TIMEOUT) { if(hcan.pRxMsg->ExtId != 0 ) { if((hcan.pRxMsg->ExtId & 0xFFFF) == RECEIVESAVECOMMANDMESSAGEID ) { #ifdef __COVERAGESCANNER__ __coveragescanner_save(); #endif } } }
The Custom IO Functions on the STM32 micro controller code look like this.
#ifdefined( __COVERAGESCANNER__ ) static int csfputs(const char *s, void *stream) { while(*s) { int counter = 0; CanTxMsgTypeDef sendMessage; sendMessage.ExtId = RETURNSAVEMESSAGEID; sendMessage.IDE = CAN_ID_EXT; sendMessage.RTR = CAN_RTR_DATA; while(*s && (counter < 8)) { sendMessage.Data[counter] = (uint8_t) *s; counter++; s++; } sendMessage.DLC = counter; hcan.pTxMsg = &sendMessage; HAL_CAN_Transmit(&hcan,TIMEOUTTIME); } return 0; } static void *csfopenappend(const char *path) { return (void*)1; } static int csfclose(void *fp) { CanTxMsgTypeDef sendMessage; sendMessage.ExtId = RETURNSAVEMESSAGEID; sendMessage.IDE = CAN_ID_EXT; sendMessage.RTR = CAN_RTR_DATA; sendMessage.Data[0] = 0; sendMessage.DLC = 0; hcan.pTxMsg = &sendMessage; HAL_CAN_Transmit(&hcan,TIMEOUTTIME); return 1; } #endif
For further information contact us.