Storage.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * This file is free software: you can redistribute it and/or modify it
  3. * under the terms of the GNU General Public License as published by the
  4. * Free Software Foundation, either version 3 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This file is distributed in the hope that it will be useful, but
  8. * WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. * See the GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License along
  13. * with this program. If not, see <http://www.gnu.org/licenses/>.
  14. *
  15. * Code by Andrew Tridgell and Siddharth Bharat Purohit
  16. */
  17. #include <AP_HAL/AP_HAL.h>
  18. #include <AP_BoardConfig/AP_BoardConfig.h>
  19. #include "Storage.h"
  20. #include "hwdef/common/flash.h"
  21. #include <AP_Filesystem/AP_Filesystem.h>
  22. #include "sdcard.h"
  23. using namespace ChibiOS;
  24. #ifndef HAL_USE_EMPTY_STORAGE
  25. extern const AP_HAL::HAL& hal;
  26. #ifndef HAL_STORAGE_FILE
  27. // using SKETCHNAME allows the one microSD to be used
  28. // for multiple vehicle types
  29. #define HAL_STORAGE_FILE "/APM/" SKETCHNAME ".stg"
  30. #endif
  31. #ifndef HAL_STORAGE_BACKUP_FILE
  32. // location of backup file
  33. #define HAL_STORAGE_BACKUP_FILE "/APM/" SKETCHNAME ".bak"
  34. #endif
  35. #define STORAGE_FLASH_RETRIES 5
  36. void Storage::_storage_open(void)
  37. {
  38. if (_initialised) {
  39. return;
  40. }
  41. #ifdef USE_POSIX
  42. // if we have failed filesystem init don't try again
  43. if (log_fd == -1) {
  44. return;
  45. }
  46. #endif
  47. _dirty_mask.clearall();
  48. #if HAL_WITH_RAMTRON
  49. using_fram = fram.init();
  50. if (using_fram) {
  51. if (!fram.read(0, _buffer, CH_STORAGE_SIZE)) {
  52. return;
  53. }
  54. _save_backup();
  55. _initialised = true;
  56. return;
  57. }
  58. // allow for FMUv3 with no FRAM chip, fall through to flash storage
  59. #endif
  60. #ifdef STORAGE_FLASH_PAGE
  61. // load from storage backend
  62. _flash_load();
  63. #elif defined(USE_POSIX)
  64. // allow for fallback to microSD based storage
  65. sdcard_retry();
  66. log_fd = AP::FS().open(HAL_STORAGE_FILE, O_RDWR|O_CREAT);
  67. if (log_fd == -1) {
  68. hal.console->printf("open failed of " HAL_STORAGE_FILE "\n");
  69. return;
  70. }
  71. int ret = AP::FS().read(log_fd, _buffer, CH_STORAGE_SIZE);
  72. if (ret < 0) {
  73. hal.console->printf("read failed for " HAL_STORAGE_FILE "\n");
  74. AP::FS().close(log_fd);
  75. log_fd = -1;
  76. return;
  77. }
  78. // pre-fill to full size
  79. if (AP::FS().lseek(log_fd, ret, SEEK_SET) != ret ||
  80. AP::FS().write(log_fd, &_buffer[ret], CH_STORAGE_SIZE-ret) != CH_STORAGE_SIZE-ret) {
  81. hal.console->printf("setup failed for " HAL_STORAGE_FILE "\n");
  82. AP::FS().close(log_fd);
  83. log_fd = -1;
  84. return;
  85. }
  86. using_filesystem = true;
  87. #endif
  88. _save_backup();
  89. _initialised = true;
  90. }
  91. /*
  92. save a backup of storage file if we have microSD available. This is
  93. very handy for diagnostics, and for moving a copy of storage into
  94. SITL for testing
  95. */
  96. void Storage::_save_backup(void)
  97. {
  98. #ifdef USE_POSIX
  99. // allow for fallback to microSD based storage
  100. sdcard_retry();
  101. int fd = AP::FS().open(HAL_STORAGE_BACKUP_FILE, O_WRONLY|O_CREAT|O_TRUNC);
  102. if (fd != -1) {
  103. AP::FS().write(fd, _buffer, CH_STORAGE_SIZE);
  104. AP::FS().close(fd);
  105. }
  106. #endif
  107. }
  108. /*
  109. mark some lines as dirty. Note that there is no attempt to avoid
  110. the race condition between this code and the _timer_tick() code
  111. below, which both update _dirty_mask. If we lose the race then the
  112. result is that a line is written more than once, but it won't result
  113. in a line not being written.
  114. */
  115. void Storage::_mark_dirty(uint16_t loc, uint16_t length)
  116. {
  117. uint16_t end = loc + length;
  118. for (uint16_t line=loc>>CH_STORAGE_LINE_SHIFT;
  119. line <= end>>CH_STORAGE_LINE_SHIFT;
  120. line++) {
  121. _dirty_mask.set(line);
  122. }
  123. }
  124. void Storage::read_block(void *dst, uint16_t loc, size_t n)
  125. {
  126. if (loc >= sizeof(_buffer)-(n-1)) {
  127. return;
  128. }
  129. _storage_open();
  130. memcpy(dst, &_buffer[loc], n);
  131. }
  132. void Storage::write_block(uint16_t loc, const void *src, size_t n)
  133. {
  134. if (loc >= sizeof(_buffer)-(n-1)) {
  135. return;
  136. }
  137. if (memcmp(src, &_buffer[loc], n) != 0) {
  138. _storage_open();
  139. memcpy(&_buffer[loc], src, n);
  140. _mark_dirty(loc, n);
  141. }
  142. }
  143. void Storage::_timer_tick(void)
  144. {
  145. if (!_initialised) {
  146. return;
  147. }
  148. if (_dirty_mask.empty()) {
  149. _last_empty_ms = AP_HAL::millis();
  150. return;
  151. }
  152. // write out the first dirty line. We don't write more
  153. // than one to keep the latency of this call to a minimum
  154. uint16_t i;
  155. for (i=0; i<CH_STORAGE_NUM_LINES; i++) {
  156. if (_dirty_mask.get(i)) {
  157. break;
  158. }
  159. }
  160. if (i == CH_STORAGE_NUM_LINES) {
  161. // this shouldn't be possible
  162. return;
  163. }
  164. #if HAL_WITH_RAMTRON
  165. if (using_fram) {
  166. if (fram.write(CH_STORAGE_LINE_SIZE*i, &_buffer[CH_STORAGE_LINE_SIZE*i], CH_STORAGE_LINE_SIZE)) {
  167. _dirty_mask.clear(i);
  168. }
  169. return;
  170. }
  171. #endif
  172. #ifdef USE_POSIX
  173. if (using_filesystem && log_fd != -1) {
  174. uint32_t offset = CH_STORAGE_LINE_SIZE*i;
  175. if (AP::FS().lseek(log_fd, offset, SEEK_SET) != offset) {
  176. return;
  177. }
  178. if (AP::FS().write(log_fd, &_buffer[offset], CH_STORAGE_LINE_SIZE) != CH_STORAGE_LINE_SIZE) {
  179. return;
  180. }
  181. if (AP::FS().fsync(log_fd) != 0) {
  182. return;
  183. }
  184. _dirty_mask.clear(i);
  185. return;
  186. }
  187. #endif
  188. #ifdef STORAGE_FLASH_PAGE
  189. // save to storage backend
  190. _flash_write(i);
  191. #endif
  192. }
  193. /*
  194. load all data from flash
  195. */
  196. void Storage::_flash_load(void)
  197. {
  198. #ifdef STORAGE_FLASH_PAGE
  199. _flash_page = STORAGE_FLASH_PAGE;
  200. hal.console->printf("Storage: Using flash pages %u and %u\n", _flash_page, _flash_page+1);
  201. if (!_flash.init()) {
  202. AP_HAL::panic("unable to init flash storage");
  203. }
  204. #else
  205. AP_HAL::panic("unable to init storage");
  206. #endif
  207. }
  208. /*
  209. write one storage line. This also updates _dirty_mask.
  210. */
  211. void Storage::_flash_write(uint16_t line)
  212. {
  213. #ifdef STORAGE_FLASH_PAGE
  214. if (_flash.write(line*CH_STORAGE_LINE_SIZE, CH_STORAGE_LINE_SIZE)) {
  215. // mark the line clean
  216. _dirty_mask.clear(line);
  217. }
  218. #endif
  219. }
  220. /*
  221. callback to write data to flash
  222. */
  223. bool Storage::_flash_write_data(uint8_t sector, uint32_t offset, const uint8_t *data, uint16_t length)
  224. {
  225. #ifdef STORAGE_FLASH_PAGE
  226. size_t base_address = hal.flash->getpageaddr(_flash_page+sector);
  227. for (uint8_t i=0; i<STORAGE_FLASH_RETRIES; i++) {
  228. if (hal.flash->write(base_address+offset, data, length)) {
  229. return true;
  230. }
  231. hal.scheduler->delay(1);
  232. }
  233. if (_flash_erase_ok()) {
  234. // we are getting flash write errors while disarmed. Try
  235. // re-writing all of flash
  236. uint32_t now = AP_HAL::millis();
  237. if (now - _last_re_init_ms > 5000) {
  238. _last_re_init_ms = now;
  239. bool ok = _flash.re_initialise();
  240. hal.console->printf("Storage: failed at %u:%u for %u - re-init %u\n",
  241. (unsigned)sector, (unsigned)offset, (unsigned)length, (unsigned)ok);
  242. }
  243. }
  244. return false;
  245. #else
  246. return false;
  247. #endif
  248. }
  249. /*
  250. callback to read data from flash
  251. */
  252. bool Storage::_flash_read_data(uint8_t sector, uint32_t offset, uint8_t *data, uint16_t length)
  253. {
  254. size_t base_address = hal.flash->getpageaddr(_flash_page+sector);
  255. const uint8_t *b = ((const uint8_t *)base_address)+offset;
  256. memcpy(data, b, length);
  257. return true;
  258. }
  259. /*
  260. callback to erase flash sector
  261. */
  262. bool Storage::_flash_erase_sector(uint8_t sector)
  263. {
  264. for (uint8_t i=0; i<STORAGE_FLASH_RETRIES; i++) {
  265. if (hal.flash->erasepage(_flash_page+sector)) {
  266. return true;
  267. }
  268. hal.scheduler->delay(1);
  269. }
  270. return false;
  271. }
  272. /*
  273. callback to check if erase is allowed
  274. */
  275. bool Storage::_flash_erase_ok(void)
  276. {
  277. // only allow erase while disarmed
  278. return !hal.util->get_soft_armed();
  279. }
  280. /*
  281. consider storage healthy if we have nothing to write sometime in the
  282. last 2 seconds
  283. */
  284. bool Storage::healthy(void)
  285. {
  286. return _initialised && AP_HAL::millis() - _last_empty_ms < 2000;
  287. }
  288. #endif // HAL_USE_EMPTY_STORAGE