2020-09-04 22:55:34 +02:00
/* Reflow Oven Controller
*
* Copyright ( C ) 2020 Mario Hüttel < mario . huettel @ gmx . net >
*
* This file is part of the Reflow Oven Controller Project .
*
* The reflow oven controller is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project .
* If not , see < http : //www.gnu.org/licenses/>.
*/
2020-09-04 23:02:23 +02:00
# ifndef __SAFETY_MEMORY_H__
# define __SAFETY_MEMORY_H__
2020-09-04 22:55:34 +02:00
# include <stdint.h>
2020-11-01 20:43:59 +01:00
# include <stddef.h>
2020-11-29 19:59:58 +01:00
# include <stdbool.h>
2020-09-04 22:55:34 +02:00
2020-09-06 19:45:45 +02:00
/** @addtogroup safety-memory
* @ {
*/
2020-09-04 22:55:34 +02:00
/**
2020-09-04 23:02:23 +02:00
* @ brief Magic number to signal a valid safety memory header .
2020-09-04 22:55:34 +02:00
*/
2020-09-04 23:02:23 +02:00
# define SAFETY_MEMORY_MAGIC 0x12AA5CB7
2020-09-04 22:55:34 +02:00
2020-09-05 17:37:56 +02:00
/**
* @ brief Error memory NOP entry
*/
# define SAFETY_MEMORY_NOP_ENTRY 0xC1AA1222
2020-09-04 22:55:34 +02:00
/**
2020-09-04 23:02:23 +02:00
* @ brief Offset address for the safety_memory_header .
* @ note Any other value than 0UL doesn ' t really make sense . Therfore , this should not be changed .
2020-09-04 22:55:34 +02:00
*/
2020-09-04 23:02:23 +02:00
# define SAFETY_MEMORY_HEADER_ADDRESS 0UL
2020-09-04 22:55:34 +02:00
2020-09-05 15:56:52 +02:00
# define SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT 32UL
2020-09-05 15:15:31 +02:00
2021-04-07 13:19:16 +02:00
# define SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE 256U
2020-09-04 22:55:34 +02:00
/**
2020-09-04 23:02:23 +02:00
* @ brief Safety memory header
2020-09-04 22:55:34 +02:00
*/
2020-09-04 23:02:23 +02:00
struct safety_memory_header {
uint32_t magic ; /**< @brief Magic. Set to @ref SAFETY_MEMORY_MAGIC */
uint32_t boot_status_offset ; /**< @brief Offset of the safety_memory_boot_status struct (in 32 bit words)*/
2020-09-04 23:51:51 +02:00
uint32_t config_overrides_offset ; /**< @brief Offset address of override entries */
uint32_t config_overrides_len ; /**< @brief Length of override entries in words */
2021-04-07 13:19:16 +02:00
uint32_t firmware_update_filename ; /**< @brief Filename of the firmware update. This string is at maximum 256 bytes long including the 0 terminator */
2020-09-04 23:02:23 +02:00
uint32_t err_memory_offset ; /**< @brief Offset of the error memory */
uint32_t err_memory_end ; /**< @brief End of the error memory. This points to the word after the error memory, containing the CRC of the whole backup RAM. */
2020-09-08 18:24:10 +02:00
uint32_t crc ; /**< @brief CRC of the header */
2020-09-04 23:02:23 +02:00
} ;
2020-09-04 22:55:34 +02:00
2020-09-04 23:02:23 +02:00
struct safety_memory_boot_status {
2020-09-05 19:00:01 +02:00
/**
* @ brief Reboot into the bootloader
*
* When this flag is set , the controller will load the bootloader to
* memory and execute it .
*/
2020-09-04 23:02:23 +02:00
uint32_t reboot_to_bootloader ;
2020-09-05 19:00:01 +02:00
/**
* @ brief Bootloader has updated the code
*
* This flag is set , if the firmware ahs been updated successfully
*/
2020-09-05 16:32:31 +02:00
uint32_t code_updated ;
2020-09-05 19:00:01 +02:00
/**
* @ brief reset_from_panic
*
* This flag is set , when entering the panic mode .
* Because the panic mode is reset by a watchdog reset ,
* this flag is needed , in order to ensure , that the panic is handled correcly after
* the watchdog reset .
*/
2020-09-05 16:32:31 +02:00
uint32_t reset_from_panic ;
2020-09-04 23:02:23 +02:00
} ;
2020-09-06 19:45:45 +02:00
/**
* @ brief The state of the safety memory
*
* This is returned by certain functions in order to signal , if the header and CRC infos are valid .
*/
2020-09-05 15:15:31 +02:00
enum safety_memory_state {
2020-09-06 19:45:45 +02:00
SAFETY_MEMORY_INIT_FRESH = 0 , /**< @brief Memory header not found */
SAFETY_MEMORY_INIT_CORRUPTED = 1 , /**< @brief Header found, but corrupt memory */
SAFETY_MEMORY_INIT_VALID_MEMORY = 2 , /**< @brief Valid header found and CRC check is valid */
2020-09-05 15:15:31 +02:00
} ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Types of error memory entries
*/
2020-09-05 15:15:31 +02:00
enum safety_memory_error_entry_type {
2020-09-06 19:45:45 +02:00
SAFETY_MEMORY_ERR_ENTRY_FLAG = 1 , /**< @brief Flag error entry. Logs a flag */
SAFETY_MEMORY_ERR_ENTRY_NOP = 2 , /**< @brief NOP entry. Has no meaning, but will be treated as a valid entry */
2020-09-05 15:15:31 +02:00
} ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Firmware internal representation of an error memory entry .
*/
2020-09-05 15:15:31 +02:00
struct error_memory_entry {
enum safety_memory_error_entry_type type ;
2020-09-05 16:32:31 +02:00
uint8_t flag_num ;
2020-09-05 20:06:13 +02:00
uint16_t counter ;
2020-09-05 15:15:31 +02:00
} ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Types of conig override entries
*/
2020-09-05 15:15:31 +02:00
enum config_override_entry_type {
SAFETY_MEMORY_CONFIG_OVERRIDE_WEIGHT = 1 ,
2021-01-25 20:59:48 +01:00
SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE = 2 ,
2020-09-05 15:15:31 +02:00
} ;
2020-09-06 19:52:44 +02:00
/**
* @ brief Weights of error flags .
*/
2020-09-06 21:05:00 +02:00
enum config_weight {
SAFETY_FLAG_CONFIG_WEIGHT_NONE = 0 , /**< @brief This flag has no global error consequence, but might be respected by certain software modules. */
SAFETY_FLAG_CONFIG_WEIGHT_PID = 1 , /**< @brief This flag will force a stop of the temperature PID controller */
SAFETY_FLAG_CONFIG_WEIGHT_PANIC = 2 , /**< @brief This flag will trigger the panic mode */
2020-09-06 19:52:44 +02:00
} ;
/**
* @ brief representation of a config override memory entry
*/
2020-09-05 15:15:31 +02:00
struct config_override {
enum config_override_entry_type type ;
union {
struct {
2020-09-05 16:32:31 +02:00
uint8_t flag ;
2020-09-06 21:05:00 +02:00
enum config_weight weight ;
2020-09-05 15:15:31 +02:00
} weight_override ;
struct {
2020-09-05 16:32:31 +02:00
uint8_t flag ;
2021-03-18 22:50:13 +01:00
bool persistence ;
} persistence_override ;
2020-09-05 15:15:31 +02:00
} entry ;
} ;
2020-09-06 19:45:45 +02:00
/**
* @ brief First time init the safety memory . This requests all clocks etc .
*
* The error memory is always vlaid after this function . At least , if it returns without error .
* The \ p found_state output tells the caller , in which state the memory was found . If it was uninitialized ,
* or corrupted , it is completely wiped and a fresh memory structure is written .
*
* @ param [ out ] found_state State the error memory was found in
* @ return 0 if successful
* @ warning Also check @ ref safety_memory_reinit
*/
2020-09-05 15:15:31 +02:00
int safety_memory_init ( enum safety_memory_state * found_state ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Same as @ ref safety_memory_init , but without specifically requesting the clock modules .
*
* Use this , if a call to @ ref safety_memory_init has already been done .
*
* @ param [ out ] found_state State the error memory was found in
* @ return 0 if successful
*/
2020-09-05 15:56:52 +02:00
int safety_memory_reinit ( enum safety_memory_state * found_state ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Get the boot status structure from safety memory
* @ param [ out ] status Status read from memory .
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_get_boot_status ( struct safety_memory_boot_status * status ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Write the boot status structure to safety memory
* @ param [ in ] status Status to write
* @ return 0 if successful
*/
2020-09-05 16:32:31 +02:00
int safety_memory_set_boot_status ( const struct safety_memory_boot_status * status ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Get the amout of error entries in the error memory . This also includes NOP entries .
* @ param [ out ] count Count
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_get_error_entry_count ( uint32_t * count ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Check the header and CRC of the safety memory .
* @ return 0 if all checks pass
*/
2020-09-05 15:15:31 +02:00
int safety_memory_check ( void ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Read an error entry from the error memory
* @ param idx Index of the entry
* @ param [ out ] entry Error entry
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_get_error_entry ( uint32_t idx , struct error_memory_entry * entry ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Insert an error entry
*
* This function inserts an error entry on the first NOP entry found in the error memory .
* If an entry is found with the same flag number , its counter is incremented by the counter value of the
* element to insert .
*
* If there are no NOPs or fitting entries in the error memory , error memory is expanded until it hits the memory
* boundary .
*
* @ param entry Error entry to insert
* @ returns 0 if successful , - 3 if out of memory , and other negative error codes
*/
2020-09-05 15:15:31 +02:00
int safety_memory_insert_error_entry ( struct error_memory_entry * entry ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Insert a config override entry at the first free location .
*
* Free locations are entries containing 0x00000000
*
* @ param config_override Config to write
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_insert_config_override ( struct config_override * config_override ) ;
2020-09-06 19:45:45 +02:00
/**
* @ brief Get count of config overrides
* @ param [ out ] count Number of overrides
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_get_config_override_count ( uint32_t * count ) ;
2020-09-06 19:45:45 +02:00
/**
2021-04-06 20:55:41 +02:00
* @ brief Get a config entry
2020-09-06 19:45:45 +02:00
* @ param idx Index of the requested entry
* @ param [ out ] config_override READ override
* @ return 0 if successful
*/
2020-09-05 15:15:31 +02:00
int safety_memory_get_config_override ( uint32_t idx , struct config_override * config_override ) ;
2021-04-07 13:19:16 +02:00
/**
* @ brief Read the set update filename from the safety backup memory
*
* \ p filename has to be large enough to hold the filename ( 255 chars ) plus the ' \0 ' - terminator .
*
* @ param [ out ] filename Array to fill in file name . May be NULL to only read the length .
* @ param [ out ] outlen String length of the filename . May be NULL to only read the file name .
* @ note \ p filename may be NULL . In this case this function can be used to read the currently set filename ' s length .
* @ warning Function will fail if both parameters are NULL
* @ return 0 if successful
*/
int safety_memory_get_update_filename ( char * filename , size_t * outlen ) ;
/**
* @ brief Set the filename of the update file
* @ param [ in ] filename Filename to set . Must be 255 chars at max ( 256 including null terminator )
* @ return 0 if successful
*/
int safety_memory_set_update_filename ( const char * filename ) ;
2021-04-06 20:55:41 +02:00
# ifndef SAFETY_MEMORY_STRIPOUT_DUMP
2020-11-01 20:43:59 +01:00
/**
* @ brief Get a base64 dump of the whole safety memory .
* @ param [ out ] buffer Buffer to write the base 64 dump into .
* @ param buffsize Size of buffer . Must be large enough to hold the data plus a ' \0 ' terminator
* @ param [ out ] used_size Number of written bytes including the ' \0 ' terminator . May be NULL .
* @ return 0 if successful
*/
int safety_memory_dump_base64 ( char * buffer , size_t buffsize , size_t * used_size ) ;
2021-04-06 20:55:41 +02:00
# endif /* SAFETY_MEMORY_STRIPOUT_DUMP */
2020-09-04 23:02:23 +02:00
# endif /* __SAFETY_MEMORY_H__ */
2020-09-06 19:45:45 +02:00
/** @} */