log.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #include "log.h"
  2. #include "rtc.h"
  3. #include "ringfs.h"
  4. #include "spi_flash.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "semphr.h"
  8. #include "rtc.h"
  9. #include "settings_api.h"
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <inttypes.h>
  13. #undef DBG
  14. #define DBG if(1)
  15. static bool archive_state = false;
  16. static bool log_state = true;
  17. static bool log_init_f = false;
  18. static bool archive_init_f = false;
  19. struct ringfs fs_log;
  20. struct ringfs fs_archive;
  21. SemaphoreHandle_t log_mutex;
  22. xQueueHandle log_queue;
  23. uint16_t log_entries_capacity;
  24. uint16_t archive_entries_capacity;
  25. void archive_task(void *params);
  26. void log_task(void *params);
  27. //
  28. static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {
  29. (void)flash;
  30. int ret;
  31. ret = spi_flash_erase_sector(address, 0);
  32. return ret;
  33. }
  34. //
  35. static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) {
  36. (void)flash;
  37. int ret;
  38. ret = spi_flash_write(address, data, size, 0);
  39. return ret;
  40. }
  41. //
  42. static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) {
  43. (void)flash;
  44. int ret;
  45. ret = spi_flash_read(address, data, size, 0);
  46. return ret;
  47. }
  48. //
  49. static struct ringfs_flash_partition ringfs_flash_log =
  50. {
  51. .sector_offset = LOG_FLASH_SECTOR_OFFSET,
  52. .sector_erase = op_sector_erase,
  53. .program = op_program,
  54. .read = op_read,
  55. };
  56. //
  57. static struct ringfs_flash_partition ringfs_flash_archive =
  58. {
  59. .sector_offset = ARCHIVE_FLASH_SECTOR_OFFSET,
  60. .sector_erase = op_sector_erase,
  61. .program = op_program,
  62. .read = op_read,
  63. };
  64. //
  65. void log_init(bool format)
  66. {
  67. DBG printf("[LOG] Init...\r\n");
  68. if (!spi_flash_desc.present)
  69. return;
  70. // ---------------------------------------------------------------------- //
  71. // Журнал
  72. ringfs_flash_log.sector_size = spi_flash_desc.sector_size;
  73. ringfs_flash_log.sector_count = LOG_FLASH_SECTOR_COUNT;
  74. ringfs_init(&fs_log, &ringfs_flash_log, LOG_ENTRY_VERSION, sizeof(log_entry_t));
  75. if (format || ringfs_scan(&fs_log) != 0) {
  76. DBG printf("FAT1 false\r\n");
  77. ringfs_format(&fs_log);
  78. }
  79. DBG printf("FAT1 true\r\n");
  80. // ---------------------------------------------------------------------- //
  81. // Архив
  82. ringfs_flash_archive.sector_size = spi_flash_desc.sector_size;
  83. ringfs_flash_archive.sector_count = ARCHIVE_FLASH_SECTOR_COUNT;
  84. ringfs_init(&fs_archive, &ringfs_flash_archive, ARCHIV_ENTRY_VERSION, sizeof(archive_entry_t));
  85. if (format || ringfs_scan(&fs_archive) != 0) {
  86. DBG printf("FAT2 false\r\n");
  87. ringfs_format(&fs_archive);
  88. }
  89. DBG printf("FAT2 true\r\n");
  90. log_mutex = xSemaphoreCreateMutex();
  91. log_entries_capacity = ringfs_capacity(&fs_log);
  92. archive_entries_capacity = ringfs_capacity(&fs_archive);
  93. xTaskCreate(archive_task, "archive_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  94. log_queue = xQueueCreate(10, sizeof(log_entry_t));
  95. xTaskCreate(log_task, "log_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  96. log_init_f = true;
  97. archive_init_f = true;
  98. }
  99. //
  100. int log_fetch(void *entry, entry_type_t entry_type, uint32_t timeout)
  101. {
  102. int ret;
  103. ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);
  104. if (ret == pdFALSE)
  105. return ret;
  106. if (entry_type == LOG_ENTRY)
  107. ret = ringfs_fetch(&fs_log, entry);
  108. else if (entry_type == ARCHIVE_ENTRY)
  109. ret = ringfs_fetch(&fs_archive, entry);
  110. else ret = -1;
  111. xSemaphoreGive(log_mutex);
  112. return ret;
  113. }
  114. //
  115. int log_discard(void *entry, entry_type_t entry_type, uint32_t timeout)
  116. {
  117. int ret;
  118. ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);
  119. if (ret == pdFALSE)
  120. return ret;
  121. if (entry_type == LOG_ENTRY)
  122. ret = ringfs_discard(&fs_log);
  123. else if (entry_type == ARCHIVE_ENTRY)
  124. ret = ringfs_discard(&fs_archive);
  125. else ret = -1;
  126. xSemaphoreGive(log_mutex);
  127. return ret;
  128. }
  129. //
  130. int log_append(void *entry, entry_type_t entry_type)
  131. {
  132. int ret;
  133. TM_RTC_t time;
  134. common_entry_t *entry_ptr = entry;
  135. log_entry_t *log_etnry_ptr;
  136. archive_entry_t *archive_etnry_ptr;
  137. ret = xSemaphoreTake(log_mutex, portMAX_DELAY);
  138. if (ret == pdFALSE)
  139. return ret;
  140. if (entry_ptr->timestamp == 0)
  141. entry_ptr->timestamp = rtc_get_ms();
  142. if (entry_type == LOG_ENTRY)
  143. {
  144. log_etnry_ptr = (log_entry_t*)entry;
  145. log_etnry_ptr->crc = crc_8(entry, sizeof(log_entry_t) - 1);
  146. ret = ringfs_append(&fs_log, entry);
  147. }
  148. else if (entry_type == ARCHIVE_ENTRY)
  149. {
  150. archive_etnry_ptr = (archive_entry_t*)entry;
  151. archive_etnry_ptr->crc = crc_8(entry, sizeof(archive_entry_t) - 1);
  152. ret = ringfs_append(&fs_archive, entry);
  153. }
  154. else ret = -1;
  155. xSemaphoreGive(log_mutex);
  156. return ret;
  157. }
  158. //
  159. uint16_t log_capacity(void)
  160. {
  161. //return ringfs_count_estimate(&fs_log);
  162. return ringfs_count_exact(&fs_log);
  163. }
  164. //
  165. uint16_t log_arch_capacity(void)
  166. {
  167. //return ringfs_count_estimate(&fs_archive);
  168. return ringfs_count_exact(&fs_archive);
  169. }
  170. // -------------------------------------------------------------------------- //
  171. // misc
  172. uint8_t crc_8(uint8_t *data, int length)
  173. {
  174. uint8_t crc = 0x00;
  175. uint8_t extract;
  176. uint8_t sum;
  177. for (int i = 0; i < length; i++) {
  178. extract = *data;
  179. for (uint8_t tmp = 8; tmp; tmp--) {
  180. sum = (crc ^ extract) & 0x01;
  181. crc >>= 1;
  182. if (sum)
  183. crc ^= 0x8C;
  184. extract >>= 1;
  185. }
  186. data++;
  187. }
  188. return crc;
  189. }
  190. // -------------------------------------------------------------------------- //
  191. // Tests
  192. // val - 0 - журнал
  193. // val - 1 - архив
  194. void log_info(uint8_t val)
  195. {
  196. if (val > 1)
  197. return;
  198. struct ringfs *fs = val == 0 ? &fs_log : &fs_archive;
  199. int capacity_flash = 0;
  200. int count_flash = 0;
  201. int count_estimate = 0;
  202. capacity_flash = ringfs_capacity(fs);
  203. count_flash = ringfs_count_exact(fs);
  204. count_estimate = ringfs_count_estimate(fs);
  205. if (val == 0)
  206. {
  207. DBG printf("Log partition capacity: %u\r\n", capacity_flash);
  208. DBG printf("Count log entry: %u\r\n", count_flash);
  209. DBG printf("Estimate count: %u\r\n", count_estimate);
  210. }
  211. else
  212. {
  213. DBG printf("Archive partition capacity: %u\r\n", capacity_flash);
  214. DBG printf("Count archive entry: %u\r\n", count_flash);
  215. DBG printf("Estimate count: %u\r\n", count_estimate);
  216. }
  217. }
  218. // val - 0 - журнал
  219. // val - 1 - архив
  220. void log_format(uint8_t val)
  221. {
  222. if (val == 0) {
  223. DBG printf("Formating log partition...\r\n");
  224. ringfs_format(&fs_log);
  225. }
  226. else if (val == 1) {
  227. DBG printf("Formating archive partition...\r\n");
  228. ringfs_format(&fs_archive);
  229. }
  230. }
  231. // Добавить n записей журнала
  232. int log_add_random_entry(uint8_t val, uint32_t cnt_entry)
  233. {
  234. int ret;
  235. log_entry_t log_entry = {0};
  236. archive_entry_t archive_entry = {0};
  237. static uint8_t log_index = 0;
  238. static uint32_t archive_index = 0;
  239. if (val == 0)
  240. {
  241. DBG printf("Appending %u archive entries\r\n", cnt_entry);
  242. for (uint32_t i = 0; i < cnt_entry; i++)
  243. {
  244. log_entry.code_type = log_index;
  245. log_entry.code_state = log_index;
  246. log_entry.channel_number = log_index;
  247. log_entry.value = (float)log_index++;
  248. ret = log_append((void*)&log_entry, LOG_ENTRY);
  249. }
  250. DBG printf("Result: %u\r\n", ret);
  251. }
  252. if (val == 1)
  253. {
  254. DBG printf("Appending %u archive entries\r\n", cnt_entry);
  255. for (uint32_t i = 0; i < cnt_entry; i++)
  256. {
  257. archive_entry.input_value = archive_index++;
  258. ret = log_append((void*)&archive_entry, ARCHIVE_ENTRY);
  259. }
  260. DBG printf("Result: %u\r\n", ret);
  261. }
  262. return ret;
  263. }
  264. //
  265. int log_add_entry(log_event_type_t type, log_event_state_t state,
  266. uint8_t channel_number, float value)
  267. {
  268. log_entry_t entry;
  269. if (!log_init_f)
  270. return -1;
  271. entry.timestamp = rtc_get_ms();
  272. entry.code_type = (uint8_t)type;
  273. entry.code_state = (uint8_t)state;
  274. entry.channel_number = channel_number;
  275. entry.value = value;
  276. xQueueSend(log_queue, &entry, 0);
  277. return 0;
  278. }
  279. //
  280. void test_fetch(void)
  281. {
  282. archive_entry_t entry = {0};
  283. log_fetch(&entry, ARCHIVE_ENTRY, portMAX_DELAY);
  284. //printf("\r\n%" PRId64 " [ms]\r\n", rtc_get_ms());
  285. printf("[entry] timestamp = % " PRId64 ", value = %u, crc = %u\r\n", entry.timestamp, entry.input_value, entry.crc);
  286. }
  287. //
  288. void log_archive_state(bool state)
  289. {
  290. archive_state = state;
  291. }
  292. //
  293. void log_log_state(bool state)
  294. {
  295. log_state = state;
  296. }
  297. void archive_task(void *params)
  298. {
  299. int ret = 0;
  300. archive_entry_t entry = {0};
  301. for (;;)
  302. {
  303. if ((!archive_state) || (!archive_init_f)) {
  304. vTaskDelay(1000);
  305. continue;
  306. }
  307. entry.timestamp = 0;
  308. entry.input_value = (uint8_t)input_state_bit;
  309. DBG printf("Append archive entry...");
  310. ret = log_append((void*)&entry, ARCHIVE_ENTRY);
  311. if (ret != 0) {
  312. DBG printf("FAIL\r\n");
  313. }
  314. else {
  315. DBG printf("OK\r\n");
  316. }
  317. vTaskDelay(settings.period_archive*1000);
  318. }
  319. }
  320. //
  321. void log_task(void *params)
  322. {
  323. int ret;
  324. log_entry_t entry;
  325. for (;;)
  326. {
  327. if (xQueueReceive(log_queue, &entry, portMAX_DELAY) == pdTRUE)
  328. {
  329. DBG printf("Try append LOG entry... ");
  330. ret = log_append((void*)&entry, LOG_ENTRY);
  331. DBG printf("Result: %i\r\n", ret);
  332. }
  333. }
  334. }