Appiko
hal_nvmc.c
1 
19 #include "hal_nvmc.h"
20 
21 #include "common_util.h"
22 #include "log.h"
23 
24 #define PAGE_START_ADDR_SUFFIX 0x1000
25 
26 uint32_t hal_nvmc_erase_page (uint32_t page_start_address)
27 {
28  if((page_start_address % PAGE_START_ADDR_SUFFIX) != 0)
29  {
30  log_printf("Invalid address\n");
31  return 1;
32  }
33  else
34  {
35  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
36  while(NRF_NVMC->READY != NVMC_READY_READY_Ready);
37  NRF_NVMC->ERASEPAGE = page_start_address;
38  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
39  while(NRF_NVMC->READY != NVMC_READY_READY_Ready);
40  return 0;
41 
42  }
43 }
44 
45 void hal_nvmc_write_data (void * p_destination, void * p_source, uint32_t size_of_data)
46 {
47  uint32_t start_address = ((uint32_t)p_destination/4)*4; // to make it to floor
48  uint32_t end_address = (CEIL_DIV(((uint32_t)p_destination + size_of_data), 4))*4; //
49  uint32_t no_of_words = (end_address - start_address)/4;
50  log_printf("Start Address : %x, End Address : %x, Size in bytes : %d, No of words : %d\n",
51  start_address, end_address, size_of_data, no_of_words);
52  //To write the first word. Before writing check if data is aligned with Word lengths
53  //And if not add proper masking.
54  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
55  while(NRF_NVMC->READY != NVMC_READY_READY_Ready);
56  uint32_t word_to_write;
57  uint32_t * loc_to_write = (uint32_t *)start_address;
58  uint32_t head_offset = ((uint32_t)p_destination - start_address)%4;
59  uint32_t * data_to_write = (uint32_t *)((uint32_t)p_source);
60  word_to_write = *((uint32_t *)(data_to_write));
61  for(uint32_t cnt = 0; cnt < head_offset; cnt++)
62  {
63  word_to_write = (word_to_write << 8) | 0x000000FF;
64  }
65  *loc_to_write = word_to_write;
66  loc_to_write++;
67 
68  if(no_of_words == 1)
69  {
70  //special case.
71  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
72  while(NRF_NVMC->READY != NVMC_READY_READY_Ready);
73  return;
74  }
75 
76  data_to_write = (uint32_t *)((uint32_t)data_to_write - head_offset);
77  //words in middlle can be written directly.
78  for(int32_t i = 1; i< (no_of_words - 1); i++)
79  {
80  data_to_write++;
81  word_to_write = (*(uint32_t*)(data_to_write));
82  *loc_to_write = word_to_write;
83  loc_to_write++;
84  }
85  //Before writing last word add proper masking at the end if data is not
86  //ending at word length
87  //for masking we will first remove unnecessary data. and then it'll be sent back
88  //to it's original desired location in word with mask
89  uint32_t tail_offset = ((no_of_words*4) - size_of_data - head_offset)%4;
90  data_to_write++;
91  word_to_write = *(data_to_write);
92  //Note: Please suggest any other logic if you come up with other than 2 loop logic
93  for(uint32_t cnt = 0; cnt < tail_offset; cnt++)
94  {
95  word_to_write = (word_to_write << 8);
96  }
97  for(uint32_t cnt=0; cnt <tail_offset; cnt++)
98  {
99  word_to_write = (word_to_write >> 8) | 0xFF000000;
100  }
101  *loc_to_write = word_to_write;
102 
103  NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
104  while(NRF_NVMC->READY != NVMC_READY_READY_Ready);
105 }
#define CEIL_DIV(A, B)
When the result of a division is not an integer, the result is rounded up to the next integer.
Definition: common_util.h:90