hsk-libs-dev  270
High Speed Karlsruhe XC878 library collection
hsk_flash.h
Go to the documentation of this file.
1 /** \file
2  * HSK Flash Facility headers
3  *
4  * This file contains function prototypes to menage information that survives
5  * a reset and allow storage within the D-Flash.
6  *
7  * It provides the \ref FLASH_STRUCT_FACTORY to create a struct with data that
8  * can be stored with hsk_flash_write() and recovered with hsk_flash_init().
9  *
10  * The D-Flash is used as a ring buffer, this distributes writes over the
11  * entire flash to gain the maximum achievable lifetime. The lifetime
12  * expectancy depends on your usage scenario and the size of the struct.
13  *
14  * Refer to section 3.3 table 20 and table 21 of the
15  * <a href="../contrib/Microcontroller-XC87x-Data-Sheet-V15-infineon.pdf">
16  * XC87x data sheet</a> for D-Flash life times.
17  *
18  * Complete coverage of the D-Flash counts as a single D-Flash cycle. Thus the
19  * formula for the expected number of write calls is:
20  * \f[
21  * writes = \lfloor 4096 / sizeof(struct) \rfloor * expectedcycles
22  * \f]
23  *
24  * - \c expectedcycles
25  * - The expected number of possible write cycles
26  * depending on the usage scenario in table 20
27  * - \c sizeof(struct)
28  * - The number of bytes the struct covers
29  * - \c floor()
30  * - Round down to the next smaller integer
31  *
32  * E.g. to store 20 bytes of configuration data, the struct factory adds 2
33  * bytes overhead to be able to check the consistency of written data, so
34  * \f$ sizeof(struct) = 22 \f$. Expecting that most of the µC use is
35  * within the first year, table 20 suggests that
36  * \f$ expectedcycles = 100000 \f$. In that case the expected number of
37  * possible hsk_flash_write() calls is 18.6 million.
38  *
39  * @author kami
40  *
41  * \section flash_byte_order Byte Order
42  *
43  * C51 stores multiple byte variables in big endian order, whereas the
44  * DPTR register, several SFRs and SDCC use little endian.
45  *
46  * If the data struct contains multibyte members such as int/uword or
47  * long/ulong, this can lead to data corruption, when switching compilers.
48  *
49  * Both the checksum and identifier are single byte values and thus will
50  * still match after a compiler switch, causing multibyte values to be
51  * restored from the flash with the wrong byte order.
52  *
53  * A byte order change can be detected with a byte order word in the struct.
54  * A BOW initialized with 0x1234 would read 0x3412 after a an order change.
55  *
56  * The suggested solution is to only create struct members with byte wise
57  * access. E.g. a ulong member may be defined in the following way:
58  * \code
59  * ubyte ulongMember[sizeof(ulong)];
60  * \endcode
61  *
62  * The value can be set like this:
63  * \code
64  * myStruct.ulongMember[0] = ulongValue;
65  * myStruct.ulongMember[1] = ulongValue >> 8;
66  * myStruct.ulongMember[2] = ulongValue >> 16;
67  * myStruct.ulongMember[3] = ulongValue >> 24;
68  * \endcode
69  *
70  * Reading works similarly:
71  * \code
72  * ulongValue = (ubyte)myStruct.ulongMember[0];
73  * ulongValue |= (uword)myStruct.ulongMember[1] << 8;
74  * ulongValue |= (ulong)myStruct.ulongMember[2] << 16;
75  * ulongValue |= (ulong)myStruct.ulongMember[3] << 24;
76  * \endcode
77  *
78  * Another alternative is to use a single ubyte[] array and store/read
79  * all data with the hsk_can_data_setSignal()/\ref hsk_can_data_getSignal()
80  * functions. Due to the bit addressing of CAN message data the
81  * maximum length of such an array would be 32 bytes (256bits).
82  *
83  * An advantage would be that less memory is required, because data
84  * no longer needs to be byte aligned.
85  */
86 
87 #ifndef _HSK_PERSIST_H_
88 #define _HSK_PERSIST_H_
89 
90 /*
91  * Required for SDCC to propagate ISR prototypes.
92  */
93 #ifdef SDCC
94 #include "../hsk_isr/hsk_isr.isr"
95 #endif /* SDCC */
96 
97 /**
98  * Ensure that a flash memory layout is defined.
99  *
100  * Either XC878_16FF (64k flash) or XC878_13FF(52k flash) are supported.
101  * XC878_16FF is the default.
102  */
103 #if !defined XC878_16FF && !defined XC878_13FF
104 #define XC878_16FF
105 #endif
106 
107 /**
108  * Used to create a struct that can be used with the hsk_flash_init()
109  * function.
110  *
111  * The hsk_flash_init() function expects certain fields to exist, in the
112  * struct, which are used to ensure the consistency of data in the flash.
113  *
114  * The following example shows how to create a struct named storableData:
115  * \code
116  * FLASH_STRUCT_FACTORY(
117  * ubyte storableByte;
118  * uword storableWord;
119  * ) storableData;
120  * \endcode
121  *
122  * @param members
123  * Struct member definitions
124  */
125 #define FLASH_STRUCT_FACTORY(members) \
126  /**
127  * This struct is a template for data that can be written to the D-Flash.
128  * It is created by invoking the \ref FLASH_STRUCT_FACTORY macro.
129  */\
130  volatile struct hsk_flash_struct {\
131  /**
132  * For data integrity/compatibilty detection.
133  *
134  * @private
135  */\
136  ubyte hsk_flash_prefix;\
137  \
138  members\
139  \
140  /**
141  * For data integrity detection.
142  *
143  * @private
144  */\
145  ubyte hsk_flash_chksum;\
146  } xdata
147 
148 /**
149  * Returned by hsk_flash_init() when the µC boots for the first time.
150  *
151  * This statements holds true <i>as far as can be told</i>. I.e. a first
152  * boot is diagnosed when all attempts to recover data have failed.
153  *
154  * Two scenarios may cause this:
155  * - No valid data has yet been written to the D-Flash
156  * - The latest flash data is corrupted, may happen in case of power
157  * down during write
158  */
159 #define FLASH_PWR_FIRST 0
160 
161 /**
162  * Returned by hsk_flash_init() after booting from a reset without power
163  * loss.
164  *
165  * The typical mark of a reset is that \c xdata memory still holds data from
166  * the previous session. If such data is found it will just be picked up.
167  *
168  * For performance reasons access to the struct is not guarded, which means
169  * that there can be no protection against data corruption, such as might
170  * be caused by a software bug like an overflow.
171  */
172 #define FLASH_PWR_RESET 1
173 
174 /**
175  * Returned by hsk_flash_init() during power on, if valid data was recovered
176  * from the D-Flash.
177  *
178  * A power on is detected when two criteria are met:
179  * - Data could not be recovered from \c xdata memory
180  * - Valid data was recovered from the D-Flash
181  */
182 #define FLASH_PWR_ON 2
183 
184 /**
185  * Recovers a struct from a previous session and sets everything up for
186  * storage of changes.
187  *
188  * There are two modes of recovery. After a fresh boot the data can be
189  * recovered from flash, if previously stored there. After a simple reset the
190  * data can still be found in XRAM and recovery can be sped up.
191  *
192  * If recovery fails entirely all members of the struct will be set to 0.
193  *
194  * @param version
195  * Version number of the persisted data structure, used to prevent
196  * initilization with incompatible data
197  * @param ptr
198  * A pointer to the xdata struct/array to persist
199  * @param size
200  * The size of the data structure to persist
201  * @retval FLASH_PWR_FIRST
202  * No valid data was recovered
203  * @retval FLASH_PWR_RESET
204  * Continue operation after a reset
205  * @retval FLASH_PWR_ON
206  * Data restore from the D-Flash succeeded
207  */
208 ubyte hsk_flash_init(void xdata * const ptr, const uword __xdata size,
209  const ubyte __xdata version);
210 
211 /**
212  * Writes the current data to the D-Flash.
213  *
214  * Ongoing writes are interrupted. Ongoing deletes are interrupted unless
215  * there is insufficient space left to write the data.
216  *
217  * @retval 1
218  * The D-Flash write is on the way
219  * @retval 0
220  * Not enough free D-Flash space to write, try again later
221  */
222 bool hsk_flash_write(void);
223 
224 #endif /* _HSK_PERSIST_H_ */
225 
uword size
The size of the data structure to persist.
Definition: hsk_flash.c:430
ubyte hsk_flash_init(void *const ptr, const uword size, const ubyte version)
Recovers a struct from a previous session and sets everything up for storage of changes.
Definition: hsk_flash.c:980
bool hsk_flash_write(void)
Writes the current data to the D-Flash.
Definition: hsk_flash.c:1116
ubyte * ptr
The pointer to the data structure to persist.
Definition: hsk_flash.c:425