21 #include "nvm_logger.h" 27 #include "common_util.h" 29 #define PAGE_METADATA_OFFSET 1 31 #define MEM_RESET_VALUE 0xFFFFFFFF 33 #define BYTE_RESET_VALUE 0xFF 37 #define BYTES_PER_PAGE 4080 39 #define PAGE_METADATA_LOC 0xFEF 41 #define IN_PAGE_LOC(x) (x && 0xFFF) 49 uint32_t page_addrs[NVM_LOGGER_MAX_PAGES];
80 static uint32_t no_avail_pages = NVM_LOG_MAX_PAGES;
84 static bool avail_pages[NVM_LOG_MAX_PAGES];
86 static uint32_t p_empty_page[1024];
100 const page_metadata_t EMPTY_PAGE_METADATA =
107 void prepare_page_metadata (uint32_t log_id);
109 void prepare_log_metadata (uint32_t * p_mem_loc, uint32_t page_no);
111 void empty_page (uint32_t page_addr);
113 void get_total_entries (uint32_t log_id)
115 for(uint32_t page_no = 0; page_no < LOGS[log_id].
no_pages; page_no++)
117 for(uint32_t loc = 0; loc < LOGS[log_id].
last_entry_no; loc++)
120 (uint32_t *)(LOGS[log_id].page_addrs[page_no]) + LOGS[log_id].entry_size*loc,
121 p_empty_page,
sizeof(uint32_t) * LOGS[log_id].entry_size) != 0)
127 log_printf(
"Total Entries LOGS[%d] : %d\n", log_id,LOGS[log_id].total_entries);
131 uint32_t get_next_loc (uint32_t log_id)
137 log_printf(
"%s\n",__func__);
138 uint32_t page_no = 0;
139 uint32_t * p_mem_loc = (uint32_t *)LOGS[log_id].page_addrs[page_no];
140 bool next_loc_found =
false;
141 uint32_t current_page_entry_no = 0;
142 while (next_loc_found ==
false)
144 if(memcmp(p_mem_loc, p_empty_page,
sizeof(uint32_t) * LOGS[log_id].entry_size) == 0)
146 next_loc_found =
true;
155 current_page_entry_no++;
157 if(current_page_entry_no >= LOGS[log_id].last_entry_no)
159 page_no = (page_no + 1)%LOGS[log_id].no_pages;
160 p_mem_loc = (uint32_t *) LOGS[log_id].page_addrs[page_no];
161 current_page_entry_no = 0;
164 log_printf(
"Next loc : %x\n", p_mem_loc);
165 return (uint32_t)p_mem_loc;
168 uint32_t update_log (log_config_t * log_config)
170 uint32_t cnt = 0;
bool empty_log_found =
false;
171 while(cnt < NVM_LOGGER_MAX_LOGS && empty_log_found ==
false)
173 if (memcmp (&LOGS[log_config->log_id], &EMPTY_LOG_METADATA,
sizeof(
log_metadata_t)) == 0)
175 empty_log_found =
true;
176 LOGS[log_config->log_id].
current_loc = log_config->start_page;
178 LOGS[log_config->log_id].
size_bytes = (log_config->entry_size );
180 LOGS[log_config->log_id].
no_pages = log_config->no_of_pages;
181 for(uint32_t page_no; page_no < log_config->no_of_pages; page_no++)
183 LOGS[log_config->log_id].
page_addrs[page_no] = log_config->start_page
184 - page_no*NVM_LOGGER_PAGE_OFFSETS;
190 log_config->log_id = (log_config->log_id + 1) % NVM_LOGGER_MAX_LOGS;
194 prepare_page_metadata (log_config->log_id);
195 return log_config->log_id;
199 void empty_page (uint32_t page_loc)
201 page_metadata_t page_metadata_buffer;
202 page_metadata_t * page_metadata_loc = (page_metadata_t *) (page_loc + NVM_LOGGER_PAGE_METADATA_ADDR);
203 memcpy(&page_metadata_buffer, page_metadata_loc,
sizeof(page_metadata_t));
204 hal_nvmc_erase_page (page_loc);
205 hal_nvmc_write_data (page_metadata_loc, &page_metadata_buffer,
sizeof(page_metadata_t));
209 void prepare_page_metadata (uint32_t log_id)
211 page_metadata_t local_page_metadata;
212 for(uint32_t page_no = 0; page_no < LOGS[log_id].
no_pages; page_no++)
214 log_printf(
"%s : %x\n",__func__, LOGS[log_id].page_addrs[page_no]);
215 page_metadata_t * page_metadata_loc = (page_metadata_t *)
216 (LOGS[log_id].page_addrs[page_no] + NVM_LOGGER_PAGE_METADATA_ADDR);
217 local_page_metadata.log_id = log_id;
218 local_page_metadata.log_page_no = page_no;
219 local_page_metadata.data_size = (uint16_t)LOGS[log_id].size_bytes;
220 hal_nvmc_write_data (page_metadata_loc, &local_page_metadata,
sizeof(page_metadata_t));
224 void prepare_log_metadata (uint32_t * p_mem_loc, uint32_t page_no)
227 log_printf(
"%s\n",__func__);
228 page_metadata_t * local_ptr = (page_metadata_t *) p_mem_loc;
229 if(memcmp (local_ptr, &EMPTY_PAGE_METADATA,
sizeof(page_metadata_t)) == 0 )
233 LOGS[local_ptr->log_id].
size_bytes = (uint32_t)local_ptr->data_size;
234 LOGS[local_ptr->log_id].entry_size =
CEIL_DIV(local_ptr->data_size,4);
235 LOGS[local_ptr->log_id].
page_addrs[local_ptr->log_page_no] =
236 ((uint32_t)p_mem_loc - NVM_LOGGER_PAGE_METADATA_ADDR);
241 avail_pages[page_no] = 0;
246 void nvm_logger_mod_init (
void)
248 log_printf(
"%s\n", __func__);
249 memset (p_empty_page, BYTE_RESET_VALUE,
sizeof(p_empty_page));
250 no_avail_pages = NVM_LOGGER_MAX_PAGES;
251 uint32_t * p_mem_loc = (uint32_t *)(NVM_LOG_PAGE0 + NVM_LOGGER_PAGE_METADATA_ADDR);
252 for (uint32_t page_no = 0; page_no < NVM_LOG_MAX_PAGES; page_no++)
254 avail_pages[page_no] = 1;
256 prepare_log_metadata (p_mem_loc,page_no);
257 p_mem_loc -= NVM_LOGGER_PAGE_OFFSETS/WORD_SIZE;
259 for(uint32_t log_no = 0; log_no < NVM_LOGGER_MAX_LOGS; log_no++)
261 get_next_loc (log_no);
268 uint32_t nvm_logger_log_init (log_config_t * log_config)
270 log_printf(
"%s\n", __func__);
271 if(no_avail_pages == 0)
273 log_printf(
"Memory Full..!!\n");
274 return NVM_LOGGER_MAX_LOGS;
276 else if((LOGS[log_config->log_id].size_bytes == log_config->entry_size) &&
277 (LOGS[log_config->log_id].no_pages == log_config->no_of_pages) &&
278 (LOGS[log_config->log_id].page_addrs[0] == log_config->start_page))
281 log_printf(
"Log already present..!!\n");
282 get_total_entries (log_config->log_id);
283 return log_config->log_id;
285 else if(no_avail_pages >= log_config->no_of_pages)
288 log_printf(
"New Log..!!\n");
289 no_avail_pages -= log_config->no_of_pages;
290 return update_log (log_config);
294 log_printf(
"Not enough Pages available..!!\n");
295 return NVM_LOGGER_MAX_LOGS;
303 void nvm_logger_feed_data (uint32_t log_id,
void * data)
305 uint32_t * p_buff = (uint32_t *)LOGS[log_id].current_loc;
307 hal_nvmc_write_data (p_buff, (uint8_t *)data,
308 LOGS[log_id].size_bytes);
315 if(LOGS[log_id].current_entry_no < LOGS[log_id].last_entry_no )
320 log_printf(
"page change..!!\n");
324 (uint32_t *)p_empty_page, BYTES_PER_PAGE) != 0)
326 log_printf(
"Erase page %x\n",LOGS[log_id].page_addrs[LOGS[log_id].current_page]);
328 empty_page (LOGS[log_id].page_addrs[LOGS[log_id].current_page]);
337 void nvm_logger_fetch_tail_data (uint32_t log_id,
void * dest_loc, uint32_t entry_no)
339 uint32_t * p_dest = (uint32_t *)dest_loc;
340 uint32_t * p_src = NULL;
341 if(entry_no >= LOGS[log_id].total_entries)
344 + 1*(LOGS[log_id].total_entries != LOGS[log_id].current_entry_no))
345 %LOGS[log_id].no_pages;
346 p_src = (uint32_t *)(LOGS[log_id].page_addrs[loc]);
347 while(memcmp(p_src, p_empty_page, LOGS[log_id].entry_size * WORD_SIZE) == 0)
349 loc = (loc + 1)%LOGS[log_id].no_pages;
350 p_src = (uint32_t *)(LOGS[log_id].page_addrs[loc]);
352 memcpy(p_dest, p_src, LOGS[log_id].size_bytes);
355 if(entry_no > LOGS[log_id].current_entry_no)
361 LOGS[log_id].no_pages) % LOGS[log_id].
no_pages;
365 %LOGS[log_id].no_pages) * (LOGS[log_id].
last_entry_no )) - entry_no *
367 p_src = (uint32_t *)(LOGS[log_id].page_addrs[entry_page]) +
369 memcpy(p_dest, p_src, LOGS[log_id].size_bytes);
374 p_src = (uint32_t *)(LOGS[log_id].current_loc) -
376 memcpy(p_dest, p_src, LOGS[log_id].size_bytes);
386 void nvm_logger_empty_log (uint32_t log_id)
388 for(uint32_t page_no = 0; page_no < LOGS[log_id].
no_pages; page_no++)
390 empty_page (LOGS[log_id].page_addrs[page_no]);
397 bool nvm_logger_is_log_empty (uint32_t log_id)
399 bool log_empty =
true;
400 for(uint32_t page_no = 0; page_no < LOGS[log_id].
no_pages; page_no++)
402 if(memcmp((uint8_t * )LOGS[log_id].page_addrs[page_no],
403 p_empty_page, NVM_LOGGER_PAGE_METADATA_ADDR) != 0)
411 void nvm_logger_release_log (uint32_t log_id)
413 for(uint32_t page_no; page_no < LOGS[log_id].
no_pages; page_no++)
415 hal_nvmc_erase_page (LOGS[log_id].page_addrs[page_no]);
Strcture for Operation time.
#define CEIL_DIV(A, B)
When the result of a division is not an integer, the result is rounded up to the next integer.