Teste semf
Kontakt

Logger

General

The main function of this module is to provide an easy and safe way of writing data cyclically or event-driven to a flash memory and read it later back. This logged data can then be transmitted to the user or developer in order to evaluate this data (e.g. which buttons were pressed, which data from sensors were received, etc.).

Any chunk of data being handled by this class can be augmented by additional information (e.g. date, time and category). This auxiliary information is stored in compressed form. An extra CRC option can be activated to validate the integrity of the logged data.

Augmenting with additional information is optional, and can also be done partially (e.g. only date and CRC).

Available log levels are: Trace, Debug, Info, Warning, Error, and Fatal.

The FlashLogger class (derived from Logger class), is responsible for writing entries (of type Logger::Entry) to memory and reading them. Entry class handles the data to be logged and attaches the additional information to it.

Different Logger instances can be created to log different payload to different sections of the memory. The payload length of one logger instance has to be the same as the data array length used in the Entry.

Initialization

For creating a FlashLogger object, a hardware flash object must be defined first. This will subsequently be also used to register it to FlashLogger object using the registerInterface function. The FlashLogger constructor requires the following four parameters.

  1. Date and time format through TimestampFormat enumeration.
    1. DATE format: DDmmYYYY (Day, Month, Year).
    2. TIME format: HHmmSShh (Hour, minutes, Seconds, hundreth of a second).
    3. DATETIME format: both options are used together.
    4. NONE: None of them is used.
  2. Payload length of the data to be logged in bytes.
  3. Permission flag for overwriting the memory when it is full of logged data.
  4. The allowed range in memory for storing entries, defined by the start and end addresses.

Should the CRC option be desired it can be activated by registering a Crc object as a second parameter using the function registerInterface.

After creating the object and registering the flash (and CRC), the initialization process must be started through the init function, in order to determine the next available position in the memory.

Initialization must be done after booting the hardware.

Minimum one Logger::Entry object must also be defined. This object is used for handling the data and augmenting it. As mentioned before, take care, that the data buffer of the entry has the same size of the payload length set in the logger’s constructor.

RLastly, an RTC object and CRC object must be defined should the logger use the datetime or crc function.

In the following example, we consider the hardware flash memory of stm32f4 microcontroller, which is already defined in semf library. The main goal of this class is to link the interface of the semf library with the hardware abstraction layer of the microcontroller.

#include "HardwareAbstraction/Stm32/stm32f4flash.h"
#include "HardwareAbstraction/Stm32/stm32f4rtc.h"
#include "Components/Storage/Logger/flashlogger.h"
#include "Components/Processing/crcsoftware.h"
#include "Components/System/systemclock.h"

// Hardware handler which is predefined in 'main.c' file.
extern RTC_HandleTypeDef hrtc; 

semf::stm32f4Rtc rtc(hrtc); // time information on hardware level
semf::SystemClock systemClock(rtc); // time information on application level
semf::Stm32F4Flash internalFlash; // flash for storing data
semf::Crc8Sofware crc; // software crc bith 8 bit length
semf::FlashLogger logger(
	internalFlash, 
	crc,
	semf::Logger::TimeFormat::DATETIME, 
	sizeof(data), 
	true /*Overwrite old entries if memory is full*/, 
	6, 
	10);
uint8_t data[32]; // data holding array
semf::Logger::Entry entry(logger); // logging data handling object

logger.initialized.connect(&onLoggerInitialized); 
logger.entryWritten.connect(&onEntryWritten); 
logger.entryAvailable.connect(&onEntryAvailable); 
logger.error.connect(&onError);
logger.init();

Usage

The following sequence diagram shows the interaction between the example application, FlashLogger, Logger::Entry and Flash class.

Since the semf library relies heavily on the signal/slot mechanism, where a signal is triggered after finishing a particular task and the signal’s associated slot is invoked in response to it, this example has four slots, which will be executed one after the other, except the onError slot, wich hopefully is not needed.

/** This function is connected to 'initialized' signal and is called after 
correct initialization. */
void onLoggerInitialized()
{	
	// filling up the data buffer
	for (int i=0, i<sizeof(data), i++)
	{
		data[i] = i;
	}	
	// set the data
	entry.setPayload(data);	
	// set its category	
	entry.setLevel(semf::Logger::Level::DEBUG_LEVEL);
	// set the current time stamp
	entry.setTimeStamp(systemClock.now());
	// add the entry to flash memory
	logger.addEntry(entry);
}

/** This function is connected to 'entryWritten' signal and is called after writing an entry to the memory successfully. */
void onEntryWritten()
{
	// Do something ...

	// For example read out the previously written entry
	// with the index 0.
	logger.getEntry(entry, 0);
}

/** This function is connected to 'entryAvailable' signal and is called after reading an entry from the memory successfully. */
void onEntryAvailable()
{
	// Copies the entrie's time stamp into a seperate object.
	semf::DateTime dt = entry.timeStamp();
	
	// Do something ...
}

/** This function is connected to 'error' signal and is called anything went wrong like CRC validation is incorrect. */
void onError()
{
	while(1) {;}
}

That’s it.

After booting with the line logger.init(); following processes will be triggered:

  1. Init function will initialize the module.
  2. Receiving the initialized signal, the program jumps into onLoggerInitialized slot and the example code will write one entry into the flash memory.
  3. Receiving the entryWritten signal, the program jumps into onEntryWritten slot and the example code will read out the one entry we wrote into the flash one step before.
  4. Receiving the entryAvailable signal, the program jumps into onEntryAvailable slot and the example code is done.

zurück zur Dokumentation