📄 osal_nv.lst
字号:
93 #define OSAL_NV_HDR_CHK 4
94 #define OSAL_NV_HDR_STAT 6
95
96 #define OSAL_NV_HDR_ITEM 2 // Length of any item of a header struct.
97 #define OSAL_NV_HDR_SIZE 8
98 #define OSAL_NV_HDR_HALF (OSAL_NV_HDR_SIZE / 2)
99
100 typedef struct
101 {
102 uint16 active;
103 uint16 inUse;
104 uint16 xfer;
105 uint16 spare;
106 } osalNvPgHdr_t;
107 // Struct member offsets.
108 #define OSAL_NV_PG_ACTIVE 0
109 #define OSAL_NV_PG_INUSE 2
110 #define OSAL_NV_PG_XFER 4
111 #define OSAL_NV_PG_SPARE 6
112
113 #define OSAL_NV_PAGE_HDR_SIZE 8
114 #define OSAL_NV_PAGE_HDR_HALF (OSAL_NV_PAGE_HDR_SIZE / 2)
115
116 typedef enum
117 {
118 eNvXfer,
119 eNvZero
120 } eNvHdrEnum;
121
122 typedef enum
123 {
124 ePgActive,
125 ePgInUse,
126 ePgXfer,
127 ePgSpare
128 } ePgHdrEnum;
129
130 /*********************************************************************
131 * GLOBAL VARIABLES
132 */
133
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
134 uint8 __xdata FBuff[4]; // Flash buffer for DMA transfer.
\ FBuff:
\ 000000 DS 4
135
136 /*********************************************************************
137 * EXTERNAL VARIABLES
138 */
139
140 /*********************************************************************
141 * EXTERNAL FUNCTIONS
142 */
143
144 extern __near_func uint8 GetCodeByte(uint32);
145 extern __near_func void halFlashDmaTrigger(void);
146
147 extern bool HalAdcCheckVdd(uint8 limit);
148
149 /*********************************************************************
150 * LOCAL VARIABLES
151 */
152
153 // Offset into the page of the first available erased space.
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
154 static uint16 pgOff[OSAL_NV_PAGES_USED];
\ ??pgOff:
\ 000000 DS 4
155
156 // Count of the bytes lost for the zeroed-out items.
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
157 static uint16 pgLost[OSAL_NV_PAGES_USED];
\ ??pgLost:
\ 000000 DS 4
158
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
159 static uint8 pgRes; // Page reserved for item compacting transfer.
\ ??pgRes:
\ 000000 DS 1
160
161 /* It saves ~100 code bytes to move a uint8* parameter/return value from findItem()
162 * to this local global.
163 */
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
164 static uint8 findPg;
\ ??findPg:
\ 000000 DS 1
165
166 /* Immediately before the voltage critical operations of a page erase or
167 * a word write, check bus voltage. If less than min, set global flag & abort.
168 * Since this is to be done at the lowest level, many void functions would have to be changed to
169 * return a value and code added to check that value before proceeding, resulting in a very
170 * expensive code size hit for implementing this properly. Therefore, use this global as follows:
171 * at the start of osal_nv_item_init/osal_nv_write, set to FALSE, and at the end, before returning,
172 * check the value. Thus, the global is an accumulator of any error that occurred in any of the
173 * attempts to modify Flash with a low bus voltage during the complicated sequence of events that
174 * may occur on any item init or write. This is much more expedient and code saving than adding
175 * return values and checking return values to early out. No matter which method is used, an NV
176 * data record may end up mangled due to the low VCC conditions. The strategy is that the headers
177 * and checksums will detect and allow recovery from such a condition.
178 *
179 * One unfortunate side-effect of using the global fail flag vice adding and checking return
180 * values, is that setItem(), unaware that setting an item Id to zero has failed due to the low VCC
181 * check, will still update the page Lost bytes counter. Having an artificially high lost byte
182 * count makes it look like there are more bytes to recover from compacting a page than there may
183 * actually be. An easy work-around it to invoke initNV() from osal_nv_item_init or osal_nv_write
184 * anytime that the failF gets set - this will re-walk all of the pages and set the page offset
185 * count and page lost bytes count to their actual values.
186 */
\ In segment XDATA_Z, align 1, keep-with-next
\ 000000 REQUIRE __INIT_XDATA_Z
187 static uint8 failF;
\ ??failF:
\ 000000 DS 1
188
189 /*********************************************************************
190 * LOCAL FUNCTIONS
191 */
192
193 static void initDMA( void );
194 static void execDMA( void );
195
196 static uint8 initNV( void );
197
198 static void setPageUse( uint8 pg, uint8 inUse );
199 static uint16 initPage( uint8 pg, uint16 id );
200 static void erasePage( uint8 pg );
201 static void compactPage( uint8 pg );
202
203 static uint16 findItem( uint16 id );
204 static uint8 initItem( uint16 id, uint16 len, void *buf );
205 static uint8 initItem2( uint16 id, uint16 len, uint8 *comPg );
206 static void setItem( uint8 pg, uint16 offset, eNvHdrEnum stat );
207
208 static uint16 calcChkB( uint16 len, uint8 *buf );
209 static uint16 calcChkF( byte pg, uint16 offset, uint16 len );
210
211 static void readHdr( uint8 pg, uint16 offset, uint8 *buf );
212 static void readWord( uint8 pg, uint16 offset, uint8 *buf );
213
214 static void writeWord( uint8 pg, uint16 offset, uint8 *buf );
215 static void writeWordD( uint8 pg, uint16 offset, uint8 *buf );
216 static void writeWordH( uint8 pg, uint16 offset, uint8 *buf );
217 static void writeBuf( uint8 pg, uint16 offset, uint16 len, uint8 *buf );
218 static void xferBuf( uint8 srcPg, uint16 srcOff, uint8 dstPg, uint16 dstOff, uint16 len );
219
220 static uint8 writeItem( uint8 pg, uint16 id, uint16 len, void *buf );
221
222 /*********************************************************************
223 * @fn initDMA
224 *
225 * @brief Initialize the DMA Channel for NV flash operations.
226 *
227 * @param none
228 *
229 * @return None
230 */
231 static void initDMA( void )
232 {
233 // Start address of the destination is the Flash Write Data register.
234 OSAL_NV_DMA_CH->dstAddrH = 0xdf;
235 OSAL_NV_DMA_CH->dstAddrL = 0xaf;
236 OSAL_NV_DMA_CH->srcAddrH = (uint16)FBuff >> 8;
237 OSAL_NV_DMA_CH->srcAddrL = (uint16)FBuff;
238
239 // Using the length field to determine how many bytes to transfer.
240 HAL_DMA_SET_VLEN( OSAL_NV_DMA_CH, HAL_DMA_VLEN_USE_LEN );
241
242 // Transfer 4 bytes at a time.
243 HAL_DMA_SET_LEN( OSAL_NV_DMA_CH, OSAL_NV_WORD_SIZE );
244
245 // Transfer size is 1 byte.
246 HAL_DMA_SET_WORD_SIZE( OSAL_NV_DMA_CH, HAL_DMA_WORDSIZE_BYTE );
247
248 // After every 4-byte transfer, must await Flash write done indication.
249 HAL_DMA_SET_TRIG_MODE( OSAL_NV_DMA_CH, HAL_DMA_TMODE_SINGLE );
250 HAL_DMA_SET_TRIG_SRC( OSAL_NV_DMA_CH, HAL_DMA_TRIG_FLASH );
251
252 // The source address is incremented by 1 byte after each transfer.
253 HAL_DMA_SET_SRC_INC( OSAL_NV_DMA_CH, HAL_DMA_SRCINC_1 );
254
255 // The destination address is constant - the Flash Write Data register.
256 HAL_DMA_SET_DST_INC( OSAL_NV_DMA_CH, HAL_DMA_DSTINC_0 );
257
258 // The DMA is to be polled and shall not issue an IRQ upon completion.
259 HAL_DMA_SET_IRQ( OSAL_NV_DMA_CH, HAL_DMA_IRQMASK_DISABLE );
260
261 // Xfer all 8 bits of a byte xfer.
262 HAL_DMA_SET_M8( OSAL_NV_DMA_CH, HAL_DMA_M8_USE_8_BITS );
263
264 // DMA memory access has highest priority.
265 HAL_DMA_SET_PRIORITY( OSAL_NV_DMA_CH, HAL_DMA_PRI_HIGH );
266 }
267
268 /*********************************************************************
269 * @fn execDMA
270 *
271 * @brief Arms and triggers a DMA write to Flash memory.
272 *
273 * @param none
274 *
275 * @return none
276 */
277 static void execDMA( void )
278 {
279 if ( !OSAL_NV_CHECK_BUS_VOLTAGE )
280 {
281 failF = TRUE;
282 return;
283 }
284
285 HAL_DMA_CLEAR_IRQ( 0 );
286
287 HAL_DMA_ARM_CH( 0 );
288
289 halFlashDmaTrigger();
290
291 while ( !(HAL_DMA_CHECK_IRQ( 0 )) );
292
293 while ( FCTL & FWBUSY );
294 }
295
296 /*********************************************************************
297 * @fn initNV
298 *
299 * @brief Initialize the NV flash pages.
300 *
301 * @param none
302 *
303 * @return TRUE if NV pages seem ok; FALSE otherwise.
304 */
\ In segment BANKED_CODE, align 1, keep-with-next
305 static uint8 initNV( void )
\ ??initNV:
306 {
\ 000000 74F6 MOV A,#-0xa
\ 000002 12.... LCALL ?BANKED_ENTER_XDATA
\ 000005 ; Saved register size: 10
\ 000005 ; Auto size: 16
\ 000005 74F0 MOV A,#-0x10
\ 000007 12.... LCALL ?ALLOC_XSTACK8
307 osalNvPgHdr_t pgHdr, ieee;
308 uint8 oldPg = OSAL_NV_PAGE_NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -