ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_task_flash.c
Go to the documentation of this file.
1 
23 #if RT_FLASH_ENABLED
24 #include "ruuvi_driver_error.h"
25 #include "ruuvi_driver_sensor.h"
26 #include "ruuvi_interface_flash.h"
27 #include "ruuvi_interface_log.h"
28 #include "ruuvi_interface_power.h"
29 #include "ruuvi_interface_yield.h"
30 #include "ruuvi_task_flash.h"
31 
32 #include <stddef.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <inttypes.h>
36 
37 #ifndef TASK_FLASH_LOG_LEVEL
38 #define TASK_FLASH_LOG_LEVEL RI_LOG_LEVEL_INFO
39 #endif
40 
41 #ifndef RT_FLASH_ERROR_FILE
42 # define RT_FLASH_ERROR_FILE 0xBFFE
43 #endif
44 
45 #ifndef RT_FLASH_ERROR_RECORD
46 # define RT_FLASH_ERROR_RECORD 0xBFFE
47 #endif
48 
49 #define LOG(msg) ri_log(TASK_FLASH_LOG_LEVEL, msg)
50 #define LOGD(msg) ri_log(RI_LOG_DEBUG, msg)
51 #define LOGW(msg) ri_log(RI_LOG_WARNING, msg)
52 #define LOGHEX(msg, len) ri_log_hex(TASK_FLASH_LOG_LEVEL, msg, len)
53 
54 typedef struct
55 {
56  rd_status_t error;
57  char filename[32];
58  int line;
59 } rt_flash_error_cause_t;
60 
61 #if 0
62 static void on_error (const rd_status_t err,
63  const bool fatal,
64  const char * file,
65  const int line)
66 {
67  if (!fatal)
68  {
69  return;
70  }
71 
72  error_cause_t error = {.error = err, .line = line };
73  rd_status_t err_code;
74  uint32_t timeout = 0;
75  strncpy (error.filename, file, sizeof (error.filename));
76  // Store reason of fatal error
77  err_code = rt_flash_store (APPLICATION_FLASH_ERROR_FILE,
78  APPLICATION_FLASH_ERROR_RECORD,
79  &error, sizeof (error));
80 
81  // Wait for flash store op to complete
82  while (RD_SUCCESS == err_code &&
83  timeout < 1000 &&
85  {
86  timeout++;
87  // Use microsecond wait to busyloop instead of millisecond wait to low-power sleep
88  // as low-power sleep may hang on interrupt context.
89  ri_delay_us (1000);
90  }
91 
92  // Try to enter bootloader, if that fails reset.
95 }
96 #endif
97 
98 #ifndef CEEDLING
99 static
100 #endif
101 void print_error_cause (void)
102 {
103  rt_flash_error_cause_t error;
104  rd_status_t err_code;
105  err_code = rt_flash_load (RT_FLASH_ERROR_FILE,
106  RT_FLASH_ERROR_RECORD,
107  &error, sizeof (error));
108 
109  if (RD_SUCCESS == err_code)
110  {
111  char error_str[128];
112  size_t index = 0;
113  index += snprintf (error_str, sizeof (error_str), "Previous fatal error: %s:%d: ",
114  error.filename, error.line);
115  index += ri_error_to_string (error.error, error_str + index,
116  sizeof (error_str) - index);
117  snprintf (error_str + index, sizeof (error_str) - index, "\r\n");
118  LOG (error_str);
119  }
120 }
121 
123 {
124  rd_status_t err_code = RD_SUCCESS;
125  err_code |= ri_flash_init();
126 
127  // Error on flash? purge, reboot
128  if (RD_SUCCESS != err_code)
129  {
130  ri_flash_purge();
131  ri_power_reset();
132  // Stop test execution here.
133 # ifdef CEEDLING
134  return err_code;
135 # endif
136  }
137 
138  // Print previous fatal error
139  print_error_cause();
140  return err_code;
141 }
142 
143 rd_status_t rt_flash_store (const uint16_t page_id, const uint16_t record_id,
144  const void * const message, const size_t message_length)
145 {
146  rd_status_t status = RD_SUCCESS;
147  status = ri_flash_record_set (page_id, record_id, message_length, message);
148 
149  if (RD_ERROR_NO_MEM == status)
150  {
151  ri_flash_gc_run();
152 
153  while (rt_flash_busy())
154  {
155  ri_yield();
156  }
157 
158  status = ri_flash_record_set (page_id, record_id, message_length, message);
159  }
160 
161  return status;
162 }
163 
164 rd_status_t rt_flash_load (const uint16_t page_id, const uint16_t record_id,
165  void * const message, const size_t message_length)
166 {
167  return ri_flash_record_get (page_id, record_id, message_length, message);
168 }
169 
170 rd_status_t rt_flash_free (const uint16_t file_id, const uint16_t record_id)
171 {
172  return ri_flash_record_delete (file_id, record_id);
173 }
174 
176 {
177  return ri_flash_gc_run();
178 }
179 
180 bool rt_flash_busy (void)
181 {
182  return ri_flash_is_busy();
183 }
184 
185 
186 
187 #else
188 
189 #include "ruuvi_driver_error.h"
190 #include <stdlib.h>
192 {
193  // Setup error reset
194  return RD_SUCCESS;
195 }
196 
197 rd_status_t rt_flash_store (const uint16_t file_id, const uint16_t record_id,
198  const void * const message, const size_t message_length)
199 {
200  return RD_SUCCESS;
201 }
202 
203 rd_status_t rt_flash_load (const uint16_t page_id, const uint16_t record_id,
204  void * const message, const size_t message_length)
205 {
206  return RD_ERROR_NOT_FOUND;
207 }
208 
209 bool rt_flash_busy (void)
210 {
211  return false;
212 }
213 #endif
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_NO_MEM
No Memory for operation.
#define RD_ERROR_NOT_FOUND
Not found.
rd_status_t ri_flash_gc_run(void)
Run garbage collection.
bool ri_flash_is_busy()
Check if flash is busy.
void ri_flash_purge(void)
Purge flash.
rd_status_t ri_flash_record_set(const uint32_t page_id, const uint32_t record_id, const size_t data_size, const void *const data)
Set data to record in page.
rd_status_t ri_flash_init(void)
rd_status_t ri_flash_record_delete(const uint32_t file_id, const uint32_t record_id)
Mark a record for deletion.
rd_status_t ri_flash_record_get(const uint32_t page_id, const uint32_t record_id, const size_t data_size, void *const data)
Get data from record in page.
size_t ri_error_to_string(rd_status_t error, char *error_string, size_t space_remaining)
Write text description of error message into given string pointer and null-terminate it....
bool rt_flash_busy(void)
Check if flash is running an operation.
rd_status_t rt_flash_gc_run(void)
Trigger garbage collection.
rd_status_t rt_flash_init(void)
Initialize flash storage.
rd_status_t rt_flash_free(const uint16_t file_id, const uint16_t record_id)
Free data from flash.
rd_status_t rt_flash_load(const uint16_t page_id, const uint16_t record_id, void *const message, const size_t message_length)
Load data from flash.
rd_status_t rt_flash_store(const uint16_t file_id, const uint16_t record_id, const void *const message, const size_t message_length)
Store data to flash.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
Interface functions to persistent flash storage.
void ri_power_enter_bootloader(void)
Enter bootloader.
void ri_power_reset(void)
Reset IC.
rd_status_t ri_yield(void)
Function which will release execution.
rd_status_t ri_delay_us(uint32_t time)
Delay a given number of microseconds.