tinyflashdb.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /*
  2. * Copyright (c) 2022-2023, smartmx - smartmx@qq.com
  3. *
  4. * SPDX-License-Identifier: MIT
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-02-03 smartmx the first version
  9. * 2022-02-08 smartmx fix bugs
  10. * 2022-02-12 smartmx fix bugs, add support for 2 byte write flash
  11. * 2022-03-15 smartmx fix bugs, add support for stm32l4 flash
  12. * 2022-08-02 smartmx add TFDB_VALUE_AFTER_ERASE_SIZE option
  13. * 2023-02-22 smartmx add dual flash index function
  14. * 2023-11-07 smartmx fix bugs, tfdb_get error when flash write in tfdb_set not success.
  15. *
  16. */
  17. #include "tinyflashdb.h"
  18. /**
  19. * check header in flash.
  20. *
  21. * @param index the data manage index.
  22. * @param rw_buffer buffer to store prepared read data or write data.
  23. *
  24. * @return TFDB_Err_Code
  25. */
  26. TFDB_Err_Code tfdb_check(const tfdb_index_t *index, uint8_t *rw_buffer)
  27. {
  28. TFDB_Err_Code result;
  29. TFDB_DEBUG("tfdb_check >\n");
  30. #if (TFDB_WRITE_UNIT_BYTES==8)
  31. /* flash_size / value_len / end_byte */
  32. result = tfdb_port_read(index->flash_addr, rw_buffer, 8);
  33. #else
  34. /* flash_size / value_len / end_byte */
  35. result = tfdb_port_read(index->flash_addr, rw_buffer, 4);
  36. #endif
  37. if (result != TFDB_NO_ERR)
  38. {
  39. //read err
  40. TFDB_DEBUG(" read err\n");
  41. goto end;
  42. }
  43. result = TFDB_HDR_ERR;
  44. /* compare flash_size */
  45. if ((rw_buffer[0] == ((index->flash_size >> 8) & 0xff)) && (rw_buffer[1] == ((index->flash_size) & 0xff)))
  46. {
  47. /* compare value_length and end_byte */
  48. if ((rw_buffer[2] == index->value_length) && (rw_buffer[3] == index->end_byte))
  49. {
  50. /* check hdr success */
  51. result = TFDB_NO_ERR;
  52. goto end;
  53. }
  54. }
  55. end:
  56. TFDB_DEBUG("tfdb_check:%d\n", result);
  57. return result;
  58. }
  59. /**
  60. * erase the flash block and init header in flash.
  61. *
  62. * @param index the data manage index.
  63. * @param rw_buffer buffer to store prepared read data or write data.
  64. *
  65. * @return TFDB_Err_Code
  66. */
  67. TFDB_Err_Code tfdb_init(const tfdb_index_t *index, uint8_t *rw_buffer)
  68. {
  69. TFDB_Err_Code result = TFDB_NO_ERR;
  70. TFDB_DEBUG("tfdb_init >\n");
  71. result = tfdb_port_erase(index->flash_addr, index->flash_size);
  72. if (result != TFDB_NO_ERR)
  73. {
  74. //erase err
  75. TFDB_DEBUG(" erase err\n");
  76. goto end;
  77. }
  78. rw_buffer[0] = ((index->flash_size >> 8) & 0xff);
  79. rw_buffer[1] = ((index->flash_size) & 0xff);
  80. rw_buffer[2] = index->value_length;
  81. rw_buffer[3] = index->end_byte;
  82. #if (TFDB_WRITE_UNIT_BYTES==8)
  83. rw_buffer[4] = index->end_byte;
  84. rw_buffer[5] = index->end_byte;
  85. rw_buffer[6] = index->end_byte;
  86. rw_buffer[7] = index->end_byte;
  87. /* flash_size / value_len / end_byte */
  88. result = tfdb_port_write(index->flash_addr, rw_buffer, 8);
  89. #else
  90. /* flash_size / value_len / end_byte */
  91. result = tfdb_port_write(index->flash_addr, rw_buffer, 4);
  92. #endif
  93. if (result != TFDB_NO_ERR)
  94. {
  95. //write err
  96. TFDB_DEBUG(" write err\n");
  97. goto end;
  98. }
  99. result = tfdb_check(index, rw_buffer);
  100. if (result != TFDB_NO_ERR)
  101. {
  102. TFDB_DEBUG(" flash ERR\n");
  103. result = TFDB_FLASH_ERR;
  104. goto end;
  105. }
  106. end:
  107. TFDB_DEBUG("tfdb_init:%d\n", result);
  108. return result;
  109. }
  110. /**
  111. * set data in flash and save the addr to addr_cache.
  112. *
  113. * @param index the data manage index.
  114. * @param rw_buffer buffer to store prepared read data or write data.
  115. * @param addr_cache the pointer to addr which is user offered, which will save read addr.
  116. * @param value_from the pointer to buffer which is user offered that need to save.
  117. *
  118. * @return TFDB_Err_Code
  119. */
  120. TFDB_Err_Code tfdb_set(const tfdb_index_t *index, uint8_t *rw_buffer, tfdb_addr_t *addr_cache, void *value_from)
  121. {
  122. TFDB_Err_Code result;
  123. tfdb_addr_t find_addr;
  124. uint8_t aligned_value_size;
  125. uint8_t sum_verify_byte;
  126. uint8_t i;
  127. #if TFDB_WRITE_MAX_RETRY
  128. uint32_t max_retry = 0;
  129. #endif
  130. TFDB_DEBUG("tfdb_set >\n");
  131. aligned_value_size = index->value_length + 2;/* data + verify + end_byte */
  132. #if (TFDB_WRITE_UNIT_BYTES==2)
  133. /* aligned with TFDB_WRITE_UNIT_BYTES */
  134. aligned_value_size = ((aligned_value_size + 1) & 0xfe);
  135. #elif (TFDB_WRITE_UNIT_BYTES==4)
  136. /* aligned with TFDB_WRITE_UNIT_BYTES */
  137. aligned_value_size = ((aligned_value_size + 3) & 0xfc);
  138. #elif (TFDB_WRITE_UNIT_BYTES==8)
  139. /* aligned with TFDB_WRITE_UNIT_BYTES */
  140. aligned_value_size = ((aligned_value_size + 7) & 0xf8);
  141. #endif
  142. TFDB_LOG("aigned size:%d\n", aligned_value_size);
  143. if (addr_cache == NULL)
  144. {
  145. start:
  146. /* addr_cache is not init. so check header first. */
  147. find_addr = 0;
  148. result = tfdb_get(index, rw_buffer, &find_addr, NULL);
  149. if(result == TFDB_NO_ERR)
  150. {
  151. find_addr = find_addr + aligned_value_size;
  152. #if (TFDB_WRITE_UNIT_BYTES==8)
  153. if(find_addr > (index->flash_addr + index->flash_size - ((index->flash_size - 8) % aligned_value_size) - aligned_value_size))
  154. #else
  155. if(find_addr > (index->flash_addr + index->flash_size - ((index->flash_size - 4) % aligned_value_size) - aligned_value_size))
  156. #endif
  157. {
  158. /* the flash block is fill */
  159. TFDB_DEBUG(" the flash is fill\n");
  160. goto init;
  161. }
  162. /* find the addr success */
  163. TFDB_LOG(" find success\n");
  164. set:
  165. /* calculate sum verify */
  166. sum_verify_byte = 0xff;
  167. for (i = 0; i < index->value_length; i++)
  168. {
  169. sum_verify_byte = ((sum_verify_byte + ((uint8_t *)(value_from))[i]) & 0xff);
  170. }
  171. write:
  172. #if TFDB_WRITE_MAX_RETRY
  173. max_retry++;
  174. if (max_retry > TFDB_WRITE_MAX_RETRY)
  175. {
  176. result = TFDB_FLASH_ERR;
  177. goto end;
  178. }
  179. #endif
  180. tfdb_memcpy(rw_buffer, value_from, index->value_length);
  181. rw_buffer[index->value_length] = sum_verify_byte;
  182. for (i = index->value_length + 1; i < aligned_value_size; i++)
  183. {
  184. /* fill aligned data with end_byte */
  185. rw_buffer[i] = index->end_byte;
  186. }
  187. result = tfdb_port_write(find_addr, rw_buffer, aligned_value_size);
  188. if (result != TFDB_NO_ERR)
  189. {
  190. TFDB_DEBUG(" write err\n");
  191. goto end;
  192. }
  193. result = tfdb_port_read(find_addr, rw_buffer, aligned_value_size);
  194. if (result != TFDB_NO_ERR)
  195. {
  196. TFDB_DEBUG(" read err\n");
  197. goto end;
  198. }
  199. if ((tfdb_memcmp(rw_buffer, value_from, index->value_length) != TFDB_MEMCMP_SAME) \
  200. || (rw_buffer[index->value_length] != sum_verify_byte)\
  201. || (rw_buffer[aligned_value_size - 1] != index->end_byte))
  202. {
  203. /* write verify failed, maybe the flash is error, try next address. */
  204. TFDB_DEBUG(" Write verify failed, try next address.\n");
  205. find_addr += aligned_value_size;
  206. #if (TFDB_WRITE_UNIT_BYTES==8)
  207. if(find_addr > (index->flash_addr + index->flash_size - ((index->flash_size - 8) % aligned_value_size) - aligned_value_size))
  208. #else
  209. if(find_addr > (index->flash_addr + index->flash_size - ((index->flash_size - 4) % aligned_value_size) - aligned_value_size))
  210. #endif
  211. {
  212. /* the flash is fill */
  213. TFDB_DEBUG(" the flash is fill\n");
  214. goto init;
  215. }
  216. else
  217. {
  218. goto write;
  219. }
  220. }
  221. else
  222. {
  223. /* write data to flash success */
  224. /* save addr to addr_cache */
  225. if (addr_cache != NULL)
  226. {
  227. *addr_cache = find_addr;
  228. }
  229. }
  230. }
  231. else if (result == TFDB_HDR_ERR)
  232. {
  233. TFDB_DEBUG(" header err\n");
  234. init:
  235. result = tfdb_init(index, rw_buffer);
  236. if (result == TFDB_NO_ERR)
  237. {
  238. after_init:
  239. #if (TFDB_WRITE_UNIT_BYTES==8)
  240. find_addr = index->flash_addr + 8;
  241. #else
  242. find_addr = index->flash_addr + 4;
  243. #endif
  244. goto set;
  245. }
  246. goto end;
  247. }
  248. else if (result == TFDB_NO_DATA)
  249. {
  250. goto after_init;
  251. }
  252. }
  253. else
  254. {
  255. if (*addr_cache == 0)
  256. {
  257. /* addr_cache is not set */
  258. goto start;
  259. }
  260. else
  261. {
  262. /* addr_cache is set */
  263. TFDB_DEBUG(" addr_cache is set\n");
  264. find_addr = *addr_cache + aligned_value_size;
  265. if (find_addr > (index->flash_addr + index->flash_size - aligned_value_size))
  266. {
  267. /* the flash is fill */
  268. TFDB_DEBUG(" the flash is fill\n");
  269. goto init;
  270. }
  271. else
  272. {
  273. goto set;
  274. }
  275. }
  276. }
  277. end:
  278. TFDB_LOG("tfdb_set:%d\n", result);
  279. return result;
  280. }
  281. /**
  282. * get the data in flash and save the addr of data to addr_cache.
  283. *
  284. * @param index the data manage index.
  285. * @param rw_buffer buffer to store prepared read data or write data.
  286. * @param addr_cache the pointer to addr which is user offered.
  287. * @param value_to the pointer to buffer which is user offered to save data.
  288. *
  289. * @return TFDB_Err_Code
  290. */
  291. TFDB_Err_Code tfdb_get(const tfdb_index_t *index, uint8_t *rw_buffer, tfdb_addr_t *addr_cache, void *value_to)
  292. {
  293. TFDB_Err_Code result;
  294. tfdb_addr_t find_addr;
  295. uint8_t aligned_value_size;
  296. uint8_t sum_verify_byte;
  297. uint8_t i;
  298. TFDB_LOG("tfdb_get >\n");
  299. aligned_value_size = index->value_length + 2;/* data + verify + end_byte */
  300. #if (TFDB_WRITE_UNIT_BYTES==2)
  301. /* aligned with TFDB_WRITE_UNIT_BYTES */
  302. aligned_value_size = ((aligned_value_size + 1) & 0xfe);
  303. #elif (TFDB_WRITE_UNIT_BYTES==4)
  304. /* aligned with TFDB_WRITE_UNIT_BYTES */
  305. aligned_value_size = ((aligned_value_size + 3) & 0xfc);
  306. #elif (TFDB_WRITE_UNIT_BYTES==8)
  307. /* aligned with TFDB_WRITE_UNIT_BYTES */
  308. aligned_value_size = ((aligned_value_size + 7) & 0xf8);
  309. #endif
  310. TFDB_LOG("aigned size:%d\n", aligned_value_size);
  311. if (addr_cache == NULL)
  312. {
  313. start:
  314. /* addr_cache is not init. so check header first. */
  315. result = tfdb_check(index, rw_buffer);
  316. if (result == TFDB_NO_ERR)
  317. {
  318. /* the header is right. so start to find data location address in flash. */
  319. #if (TFDB_WRITE_UNIT_BYTES==8)
  320. find_addr = index->flash_addr + index->flash_size - ((index->flash_size - 8) % aligned_value_size) - aligned_value_size;
  321. while ((find_addr) >= (index->flash_addr + 8))
  322. #else
  323. find_addr = index->flash_addr + index->flash_size - ((index->flash_size - 4) % aligned_value_size) - aligned_value_size;
  324. while ((find_addr) >= (index->flash_addr + 4))
  325. #endif
  326. {
  327. /* start to find value */
  328. result = tfdb_port_read(find_addr, rw_buffer, aligned_value_size);
  329. if (result != TFDB_NO_ERR)
  330. {
  331. TFDB_DEBUG(" read err\n");
  332. goto end;
  333. }
  334. if (rw_buffer[aligned_value_size - 1] == index->end_byte)
  335. {
  336. /* find value addr success */
  337. break;
  338. }
  339. if(find_addr >= aligned_value_size)
  340. {
  341. find_addr -= aligned_value_size;
  342. }
  343. else
  344. {
  345. break;
  346. }
  347. }
  348. verify:
  349. if(rw_buffer[aligned_value_size - 1] != index->end_byte)
  350. {
  351. TFDB_LOG("end_byte err\n");
  352. goto read_next;
  353. }
  354. sum_verify_byte = 0xff;
  355. /* calculate sum verify */
  356. for (i = 0; i < index->value_length; i++)
  357. {
  358. sum_verify_byte = ((sum_verify_byte + rw_buffer[i]) & 0xff);
  359. }
  360. if (sum_verify_byte != rw_buffer[index->value_length])
  361. {
  362. /* not right data, maybe the flash is broken. */
  363. TFDB_LOG("verify err:%02x,%02x\n", sum_verify_byte, rw_buffer[index->value_length]);
  364. read_next:
  365. #if (TFDB_WRITE_UNIT_BYTES==8)
  366. if (find_addr >= (index->flash_addr + 8 + aligned_value_size))
  367. #else
  368. if (find_addr >= (index->flash_addr + 4 + aligned_value_size))
  369. #endif
  370. {
  371. find_addr = find_addr - aligned_value_size;
  372. result = tfdb_port_read(find_addr, rw_buffer, aligned_value_size);
  373. if (result != TFDB_NO_ERR)
  374. {
  375. TFDB_DEBUG(" read err\n");
  376. goto end;
  377. }
  378. goto verify;
  379. }
  380. else
  381. {
  382. TFDB_DEBUG(" no data in flash\n");
  383. result = TFDB_NO_DATA;
  384. goto end;
  385. }
  386. }
  387. else
  388. {
  389. TFDB_DEBUG(" find success\n");
  390. result = TFDB_NO_ERR;
  391. if(value_to != NULL)
  392. {
  393. tfdb_memcpy(value_to, rw_buffer, index->value_length);
  394. }
  395. if (addr_cache != NULL)
  396. {
  397. *addr_cache = find_addr;
  398. }
  399. }
  400. }
  401. else
  402. {
  403. TFDB_DEBUG(" header err\n");
  404. result = TFDB_HDR_ERR;
  405. goto end;
  406. }
  407. }
  408. else
  409. {
  410. if (*addr_cache == 0)
  411. {
  412. /* addr_cache is not set */
  413. goto start;
  414. }
  415. else
  416. {
  417. find_addr = *addr_cache;
  418. result = tfdb_port_read(find_addr, rw_buffer, aligned_value_size);
  419. if (result != TFDB_NO_ERR)
  420. {
  421. TFDB_DEBUG(" read err\n");
  422. goto end;
  423. }
  424. goto verify;
  425. }
  426. }
  427. end:
  428. TFDB_LOG("tfdb_get:%d\n", result);
  429. return result;
  430. }
  431. /**
  432. * get the previous data in flash and save the addr of data to addr_cache.
  433. *
  434. * @param index the data manage index.
  435. * @param rw_buffer buffer to store prepared read data or write data.
  436. * @param addr_cache the pointer to addr which is user offered.
  437. * @param value_to the pointer to buffer which is user offered to save data.
  438. *
  439. * @return TFDB_Err_Code
  440. */
  441. TFDB_Err_Code tfdb_get_pre(const tfdb_index_t *index, uint8_t *rw_buffer, tfdb_addr_t *addr_cache, tfdb_addr_t *pre_addr_cache, void *value_to)
  442. {
  443. TFDB_Err_Code result;
  444. uint8_t aligned_value_size;
  445. tfdb_addr_t find_addr;
  446. TFDB_LOG("tfdb_get_pre >\n");
  447. if(addr_cache == NULL)
  448. {
  449. goto prepare;
  450. }
  451. else
  452. {
  453. if(*addr_cache != 0)
  454. {
  455. find_addr = *addr_cache;
  456. TFDB_LOG("find_addr:%x\n", find_addr);
  457. find:
  458. aligned_value_size = index->value_length + 2; /* data + verify + end_byte */
  459. #if (TFDB_WRITE_UNIT_BYTES==2)
  460. /* aligned with TFDB_WRITE_UNIT_BYTES */
  461. aligned_value_size = ((aligned_value_size + 1) & 0xfe);
  462. #elif (TFDB_WRITE_UNIT_BYTES==4)
  463. /* aligned with TFDB_WRITE_UNIT_BYTES */
  464. aligned_value_size = ((aligned_value_size + 3) & 0xfc);
  465. #elif (TFDB_WRITE_UNIT_BYTES==8)
  466. /* aligned with TFDB_WRITE_UNIT_BYTES */
  467. aligned_value_size = ((aligned_value_size + 7) & 0xf8);
  468. #endif
  469. TFDB_LOG("aigned size:%d\n", aligned_value_size);
  470. #if (TFDB_WRITE_UNIT_BYTES==8)
  471. if(find_addr >= (index->flash_addr + 8 + aligned_value_size))
  472. #else
  473. if(find_addr >= (index->flash_addr + 4 + aligned_value_size))
  474. #endif
  475. {
  476. find_addr = find_addr - aligned_value_size;
  477. result = tfdb_get(index, rw_buffer, &find_addr, value_to);
  478. if(result == TFDB_NO_ERR)
  479. {
  480. if(pre_addr_cache != NULL)
  481. {
  482. *pre_addr_cache = find_addr;
  483. }
  484. }
  485. }
  486. else
  487. {
  488. /* no old data. */
  489. result = TFDB_NO_PRE_DATA;
  490. }
  491. }
  492. else
  493. {
  494. prepare:
  495. find_addr = 0;
  496. result = tfdb_get(index, rw_buffer, &find_addr, value_to);
  497. if(result != TFDB_NO_ERR)
  498. {
  499. goto end;
  500. }
  501. if(addr_cache != NULL)
  502. {
  503. *addr_cache = find_addr;
  504. }
  505. goto find;
  506. }
  507. }
  508. end:
  509. TFDB_LOG("tfdb_get_pre:%d\n", result);
  510. return result;
  511. }
  512. /**
  513. * judge which seq is new.
  514. *
  515. * @param seq the pointer to seq[2] buffer.
  516. *
  517. * @return uint8_t which seq is new, 0xff means all seq is illegal.
  518. */
  519. static uint8_t tfdb_dual_judge(uint16_t *seq)
  520. {
  521. /* seq range: 0x00ff -> 0x0ff0 -> 0xff00 */
  522. switch (seq[0])
  523. {
  524. case 0xff00:
  525. if (seq[1] == 0x00ff)
  526. {
  527. return 1;
  528. }
  529. else
  530. {
  531. return 0;
  532. }
  533. case 0x0ff0:
  534. if (seq[1] == 0xff00)
  535. {
  536. return 1;
  537. }
  538. else
  539. {
  540. return 0;
  541. }
  542. case 0x00ff:
  543. if (seq[1] == 0x0ff0)
  544. {
  545. return 1;
  546. }
  547. else
  548. {
  549. return 0;
  550. }
  551. default:
  552. if ((seq[1] == 0x00ff) || (seq[1] == 0x0ff0) || (seq[1] == 0xff00))
  553. {
  554. return 1;
  555. }
  556. break;
  557. }
  558. return 0xff;
  559. }
  560. /**
  561. * get next seq from given seq.
  562. *
  563. * @param seq the pointer to seq[2] buffer.
  564. *
  565. * @return uint8_t which seq is new, 0xff means all seq is illegal.
  566. */
  567. static uint16_t tfdb_dual_get_next_seq(uint16_t seq)
  568. {
  569. /* seq range: 0x00ff -> 0x0ff0 -> 0xff00 */
  570. if (seq == 0x00ff)
  571. {
  572. return 0x0ff0;
  573. }
  574. else if (seq == 0x0ff0)
  575. {
  576. return 0xff00;
  577. }
  578. else
  579. {
  580. return 0x00ff;
  581. }
  582. }
  583. /**
  584. * get the data in flash and save the addr and seq to cache.
  585. *
  586. * @param index the data manage index.
  587. * @param rw_buffer buffer to store prepared read data or write data.
  588. * @param rw_buffer_bak buffer to store prepared read data or write data.
  589. * @param cache the pointer to addr which is user offered, which will save read addr and seq.
  590. * @param value_from the pointer to buffer which is user offered that need to save.
  591. *
  592. * @return TFDB_Err_Code
  593. */
  594. TFDB_Err_Code tfdb_dual_get(const tfdb_dual_index_t *index, uint8_t *rw_buffer, uint8_t *rw_buffer_bak, tfdb_dual_cache_t *cache, void *value_to)
  595. {
  596. TFDB_Err_Code rresult = TFDB_NO_ERR;
  597. TFDB_Err_Code result[2];
  598. uint8_t judge_state;
  599. if (cache != NULL)
  600. {
  601. judge_state = tfdb_dual_judge(cache->seq);
  602. TFDB_DEBUG("tfdb_dual_judge:%d\n", judge_state);
  603. /* usually, we just read value once during the initializing. */
  604. if (judge_state == 0xff)
  605. {
  606. result[0] = tfdb_get(&index->indexes[0], rw_buffer, &(cache->addr_cache[0]), rw_buffer_bak);
  607. if (result[0] == TFDB_NO_ERR)
  608. {
  609. cache->seq[0] = (rw_buffer_bak[0] << 8) | (rw_buffer_bak[1]);
  610. tfdb_memcpy(value_to, &(rw_buffer_bak[2]), index->indexes[0].value_length - 2);
  611. }
  612. else
  613. {
  614. cache->seq[0] = 0;
  615. }
  616. result[1] = tfdb_get(&index->indexes[1], rw_buffer, &(cache->addr_cache[1]), rw_buffer_bak);
  617. if (result[1] == TFDB_NO_ERR)
  618. {
  619. cache->seq[1] = (rw_buffer_bak[0] << 8) | (rw_buffer_bak[1]);
  620. }
  621. else
  622. {
  623. cache->seq[1] = 0;
  624. }
  625. judge_state = tfdb_dual_judge(cache->seq);
  626. if (judge_state == 1)
  627. {
  628. tfdb_memcpy(value_to, &(rw_buffer_bak[2]), index->indexes[1].value_length - 2);
  629. }
  630. else if (judge_state == 0xff)
  631. {
  632. rresult = TFDB_SEQ_ERR;
  633. }
  634. }
  635. else
  636. {
  637. rresult = tfdb_get(&index->indexes[judge_state], rw_buffer, &(cache->addr_cache[judge_state]), rw_buffer_bak);
  638. if (rresult == TFDB_NO_ERR)
  639. {
  640. tfdb_memcpy(value_to, &(rw_buffer_bak[2]), index->indexes[judge_state].value_length - 2);
  641. }
  642. else
  643. {
  644. /* block not right, don't read another block. */
  645. }
  646. }
  647. }
  648. else
  649. {
  650. rresult = TFDB_CACHE_ERR;
  651. }
  652. return rresult;
  653. }
  654. /**
  655. * set data in flash and save the addr and seq to cache.
  656. *
  657. * @param index the data manage index.
  658. * @param rw_buffer buffer to store prepared read data or write data.
  659. * @param rw_buffer_bak buffer to store prepared read data or write data.
  660. * @param cache the pointer to addr which is user offered, which will save read addr and seq.
  661. * @param value_from the pointer to buffer which is user offered that need to save.
  662. *
  663. * @return TFDB_Err_Code
  664. */
  665. TFDB_Err_Code tfdb_dual_set(const tfdb_dual_index_t *index, uint8_t *rw_buffer, uint8_t *rw_buffer_bak, tfdb_dual_cache_t *cache, void *value_from)
  666. {
  667. TFDB_Err_Code rresult = TFDB_NO_ERR;
  668. TFDB_Err_Code result[2];
  669. uint8_t judge_state;
  670. uint16_t write_seq;
  671. if (cache != NULL)
  672. {
  673. judge_state = tfdb_dual_judge(cache->seq);
  674. TFDB_DEBUG("tfdb_dual_judge:%d\n", judge_state);
  675. /* usually, we just read value once during the initializing. */
  676. if (judge_state != 0xff)
  677. {
  678. write:
  679. write_seq = tfdb_dual_get_next_seq(cache->seq[judge_state]);
  680. judge_state = 1 - judge_state; /* we need to write in another flash block. */
  681. rw_buffer_bak[0] = (uint8_t)(write_seq >> 8);
  682. rw_buffer_bak[1] = (uint8_t)write_seq;
  683. tfdb_memcpy(&(rw_buffer_bak[2]), value_from, index->indexes[judge_state].value_length - 2);
  684. result[judge_state] = tfdb_set(&index->indexes[judge_state], rw_buffer, &(cache->addr_cache[judge_state]), rw_buffer_bak);
  685. if (result[judge_state] == TFDB_NO_ERR)
  686. {
  687. cache->seq[judge_state] = write_seq;
  688. }
  689. else
  690. {
  691. /* block is error, do not write to another block, for keeping the old data safe.
  692. * if you want to write in another block, please use tfdb_set directly. */
  693. rresult = judge_state + TFDB_FLASH1_ERR;
  694. }
  695. }
  696. else
  697. {
  698. result[0] = tfdb_get(&index->indexes[0], rw_buffer, &(cache->addr_cache[0]), rw_buffer_bak);
  699. if (result[0] == TFDB_NO_ERR)
  700. {
  701. cache->seq[0] = (rw_buffer_bak[0] << 8) | (rw_buffer_bak[1]);
  702. }
  703. else
  704. {
  705. cache->seq[0] = 0;
  706. }
  707. result[1] = tfdb_get(&index->indexes[1], rw_buffer, &(cache->addr_cache[1]), rw_buffer_bak);
  708. if (result[1] == TFDB_NO_ERR)
  709. {
  710. cache->seq[1] = (rw_buffer_bak[0] << 8) | (rw_buffer_bak[1]);
  711. }
  712. else
  713. {
  714. cache->seq[1] = 0;
  715. }
  716. judge_state = tfdb_dual_judge(cache->seq);
  717. if (judge_state == 0xff)
  718. {
  719. judge_state = 0; /* first write 0 block. */
  720. }
  721. goto write;
  722. }
  723. }
  724. else
  725. {
  726. return TFDB_CACHE_ERR;
  727. }
  728. return rresult;
  729. }