zhaohe 1 year ago
parent
commit
271e5fe495
  1. 5
      README.md
  2. 2
      app/src/basic/version.h
  3. 105
      app/src/ble_cmd_process_service.c
  4. 4
      app/src/ble_cmd_process_service.h
  5. 8
      app/src/board/board.h
  6. 14
      app/src/one_conduction_main.c
  7. 3
      app/src/sample_data_manager.c
  8. 8
      app/src/sample_data_manager.h
  9. 61
      app/src/zeeprom_fs.c
  10. 60
      app/src/zeeprom_fs.h
  11. 2
      ify_hrs_protocol
  12. 2
      libznordic
  13. 16738
      release/V9/one_lead_ecg_v9.hex
  14. BIN
      release/V9/one_lead_ecg_v9.zip

5
README.md

@ -27,6 +27,11 @@ V8:
4. 解决偶尔关机时,设备启动失败的异常。
5. 优化电池电量范围
V9:
1.读取头部信息包添加checksum字段,向前兼容
2.修正文件系统读取时,读取的数据长度不正确的问题
3.修正数据上传时,数据长度不正确的问题
4.
测试:
1. 电池电量测试

2
app/src/basic/version.h

@ -2,7 +2,7 @@
#define CATEGORY "M1001" // 데돔젬
#define MANUFACTURER_NAME "iflytop"
#define FIRMWARE_VERSION (8)
#define FIRMWARE_VERSION (9)
#define BLESTACK_VERSION 1
#define BOOTLOADER_VERSION 1
#define HARDWARE_VERSION (1)

105
app/src/ble_cmd_process_service.c

@ -15,8 +15,10 @@ APP_TIMER_DEF(m_record_upload_tmr); //
APP_TIMER_DEF(m_record_upload_finish_packet_report_tmr); //
static uint8_t txbuf[128];
static uint8_t reportbuf[128];
static bool m_realtime_report_state = false;
static bool m_isupload_data_state = false;
static bool m_realtime_report_state = false;
static int m_upload_record_state = 0;
static uint32_t m_upload_data_state_enter_tp = 0;
static bool m_ble_cmder_is_inited = false;
static uint32_t m_report_data_sumcheckcode = 0;
@ -141,64 +143,71 @@ static void record_upload_finish_packet_report_tmr_cb(void* p_context) { //
static void record_upload_tmr_cb(void* p_context) { //
if (!m_isupload_data_state) return;
// sample_data_mgr_read
if (m_remaindatalen == 0) {
memset(datacache, 0, sizeof(datacache));
int32_t rdsize = sample_data_mgr_read(m_upload_fd, datacache, sizeof(datacache));
if (rdsize <= 0) {
ZLOGI("read file end,stop upload");
ZERROR_CHECK(app_timer_start(m_record_upload_finish_packet_report_tmr, APP_TIMER_TICKS(30), (void*)m_report_data_sumcheckcode));
ble_stop_upload_record();
if (m_upload_record_state == 0) return;
if (m_upload_record_state == 1) {
if (m_remaindatalen == 0) {
memset(datacache, 0, sizeof(datacache));
int32_t rdsize = sample_data_mgr_read(m_upload_fd, datacache, sizeof(datacache));
if (rdsize <= 0) {
ZLOGI("read file end,stop upload");
m_upload_record_state = 2;
m_upload_data_state_enter_tp = znordic_getpower_on_ms();
return;
}
m_remaindatalen = rdsize;
}
if (m_remaindatalen == 0) {
return;
}
m_remaindatalen = rdsize;
}
if (m_remaindatalen == 0) {
return;
}
int32_t mtusize = zble_module_get_mtu_size();
mtusize = mtusize < 128 ? mtusize : 128;
uint8_t* data = datacache + (sizeof(datacache) - m_remaindatalen);
int len = m_remaindatalen > mtusize ? mtusize : m_remaindatalen;
int32_t mtusize = zble_module_get_mtu_size();
mtusize = mtusize < 128 ? mtusize : 128;
ZLOGI("upload %d %d %d", len, m_remaindatalen, mtusize);
if (!zdatachannel_is_connected()) {
ZLOGI("ble is disconnected,stop upload");
ble_stop_upload_record();
return;
}
uint8_t* data = datacache + (sizeof(datacache) - m_remaindatalen);
int len = m_remaindatalen > mtusize ? mtusize : m_remaindatalen;
uint32_t suc = zdatachannel_block_data_send2(data, len);
if (suc != NRF_SUCCESS) {
if (suc == NRF_ERROR_INVALID_STATE) {
// 使notify
ZLOGI("ble unenable notify,stop upload");
ZLOGI("upload %d %d %d", len, m_remaindatalen, mtusize);
if (!zdatachannel_is_connected()) {
ZLOGI("ble is disconnected,stop upload");
ble_stop_upload_record();
return;
} else if (suc == NRF_ERROR_BUSY || suc == NRF_ERROR_RESOURCES) {
//
return;
} else {
ZLOGI("ble send error,stop upload %x", suc);
}
uint32_t suc = zdatachannel_block_data_send2(data, len);
if (suc != NRF_SUCCESS) {
if (suc == NRF_ERROR_INVALID_STATE) {
// 使notify
ZLOGI("ble unenable notify,stop upload");
ble_stop_upload_record();
return;
} else if (suc == NRF_ERROR_BUSY || suc == NRF_ERROR_RESOURCES) {
//
return;
} else {
ZLOGI("ble send error,stop upload %x", suc);
ble_stop_upload_record();
return;
}
}
for (uint32_t i = 0; i < len; i++) {
m_report_data_sumcheckcode += data[i];
}
m_remaindatalen -= len;
} else {
if (znordic_haspassed_ms(m_upload_data_state_enter_tp) > 30) {
ble_cmder_report_upload_finish_event(m_report_data_sumcheckcode);
ble_stop_upload_record();
return;
}
}
for (uint32_t i = 0; i < len; i++) {
m_report_data_sumcheckcode += data[i];
}
m_remaindatalen -= len;
}
int ble_start_upload_record(sample_data_filename_t* recordid) {
//
//
//
if (ds_now_state() != kdevice_state_home) {
if (ds_now_state() != kdevice_state_home && ds_now_state() != kdevice_state_charging) {
return kifyhrs_ecode_device_busy;
}
@ -208,23 +217,21 @@ int ble_start_upload_record(sample_data_filename_t* recordid) {
}
ZERROR_CHECK(app_timer_start(m_record_upload_tmr, APP_TIMER_TICKS(15), NULL));
m_isupload_data_state = true;
m_upload_record_state = 1;
m_remaindatalen = 0;
m_report_data_sumcheckcode = 0;
return 0;
}
int ble_stop_upload_record() {
m_isupload_data_state = false;
m_upload_record_state = 0;
app_timer_stop(m_record_upload_tmr);
if (m_upload_fd > 0) {
sample_data_mgr_close(m_upload_fd);
m_upload_fd = 0;
}
return 0;
}
bool ble_is_upload_record() { return m_isupload_data_state; }
bool ble_is_upload_record() { return m_upload_record_state != 0; }
/*******************************************************************************
* UTILS *
@ -394,7 +401,7 @@ void ble_cmder_process_rx(uint8_t* rx, int len) {
receipt->captureRate = SAMPLE_RATE / 10;
receipt->capturePrecision = SAMPLE_PRECISION;
receipt->compressAlgorithm = 0;
receipt->checksum = fileinfo->checksum;
zdatachannel_data_send2(txbuf, sendlen);
}

4
app/src/ble_cmd_process_service.h

@ -9,7 +9,9 @@ void ble_cmder_process_rx(uint8_t* rx, int len);
void ble_cmder_start_adv();
void ble_cmder_stop_adv();
void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data0, uint16_t data1, uint16_t data2, uint16_t data3,uint16_t data4);
void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data0, uint16_t data1, uint16_t data2, uint16_t data3, uint16_t data4);
void ble_cmder_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1);
void ble_cmder_report_upload_finish_event(uint32_t sumcheckcode);
void ble_cmder_report_sample_finish_event();
bool ble_is_upload_record();
int ble_stop_upload_record();

8
app/src/board/board.h

@ -42,9 +42,9 @@
#define LIGHT_PWM_INSTANCE 1
#define APP_BATTERY_PROTECT_LEVEL 2 // 低于此电量不能开机,保护电池
#define APP_AUTO_STANDY_BATTERY_LEVEL 10 // 低于此电量自动待机,保持时钟
#define APP_WORK_BATTERY_LEVEL 15 // Main初始化时候和从standy切换到work的时候,检查这个电量
#define APP_LOW_BATTERY_WARNING_LIMIT 20 //
#define APP_AUTO_STANDY_BATTERY_LEVEL 5 // 低于此电量自动待机,保持时钟
#define APP_WORK_BATTERY_LEVEL 10 // Main初始化时候和从standy切换到work的时候,检查这个电量
#define APP_LOW_BATTERY_WARNING_LIMIT 20 //
#define LOW_BATTERY_REMINDER_DELAY_MS 3000
#define BLE_UNCONNECTED_OVERTIME_S 300
#define BLE_UNCONNECTED_OVERTIME_S 300

14
app/src/one_conduction_main.c

@ -84,7 +84,16 @@ static void power_off() {
BoardLight_unload();
BoardBeepCtrl_unload();
ble_stop_upload_record();
zble_module_disconnect();
for (size_t i = 0; i < 100; i++) {
nrf_delay_ms(10);
if (!zble_module_is_connected()) {
break;
}
}
ble_cmder_stop_adv();
ble_cmder_uninit();
m_poweronflag = false;
@ -228,6 +237,9 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
ds_change_to_state(kdevice_state_keep_still);
dsp_mgr_change_to_preparePage();
hwss_start_prepare_capture();
if (ble_is_upload_record()) {
ble_stop_upload_record();
}
}
}
@ -236,7 +248,7 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
state_machine__change_to_standby_state();
} //
else if (zble_module_is_connected() && zdatachannel_last_rx_data_haspassed_s() >= BLE_UNCONNECTED_OVERTIME_S) {
else if (!ble_is_upload_record() && zble_module_is_connected() && zdatachannel_last_rx_data_haspassed_s() >= BLE_UNCONNECTED_OVERTIME_S) {
ZLOGI("auto sleep because ble unconnected");
state_machine__change_to_standby_state();
}

3
app/src/sample_data_manager.c

@ -31,7 +31,8 @@ sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list() { //
sample_data_fileinfo_t* fileinfo = &fileinfocache[fileinfocache_count];
fileinfo->fileuuid = sectorinfo->fileuuid;
memcpy(fileinfo->filename, sectorinfo->filename, sizeof(fileinfo->filename));
fileinfo->size = zeeprom_fs_get_filesize_by_fileuuid(fileinfo->fileuuid);
fileinfo->size = zeeprom_fs_get_filesize_by_fileuuid(fileinfo->fileuuid);
fileinfo->checksum = zeeprom_fs_get_checksum_by_fileuuid(fileinfo->fileuuid);
fileinfo_list.fileinfo[fileinfo_list.count] = fileinfo;
fileinfo_list.count++;

8
app/src/sample_data_manager.h

@ -7,7 +7,6 @@
void sample_data_mgr_init();
typedef struct {
uint8_t year;
uint8_t month;
@ -19,9 +18,10 @@ typedef struct {
} sample_data_filename_t;
typedef struct {
uint8_t filename[8];
int32_t fileuuid;
int32_t size;
uint8_t filename[8];
int32_t fileuuid;
int32_t size;
uint32_t checksum;
} sample_data_fileinfo_t;
typedef struct {

61
app/src/zeeprom_fs.c

@ -31,10 +31,11 @@ static int32_t sector_mgr_file_get_size(int32_t fileuuid);
static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid);
static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector);
static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector);
static int32_t sector_mgr_file_get_checksum(int32_t fileuuid);
static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len);
static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len);
static int32_t compute_checksum(uint8_t* data, uint16_t len);
static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len);
static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len);
static uint32_t compute_checksum(const uint8_t* data, uint16_t len);
/*******************************************************************************
* CODE *
@ -45,8 +46,8 @@ int zeeprom_fs_init() { //
SingleLeadECG_eeprom_init();
if (!m_eeprom_header_inited) {
zeeprom_read(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header));
int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum));
if (checksum_val != m_eeprom_header.checksum) {
uint32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.sector_info_headers_checksum));
if (checksum_val != m_eeprom_header.sector_info_headers_checksum) {
memset(&m_eeprom_header, 0, sizeof(m_eeprom_header));
}
}
@ -101,11 +102,13 @@ int zeeprom_fs_open(uint8_t* filename, wrflag_t wrflag) {
memcpy(sectorHeaderInfo->filename, filename, 8);
sectorHeaderInfo->sector_index_in_file = 0;
sectorHeaderInfo->datalen = 0;
sectorHeaderInfo->fileuuid = m_eeprom_header.fileuuid++;
sectorHeaderInfo->sector_data_checksum = 0;
sectorHeaderInfo->fileuuid = m_eeprom_header.fileuuid_cnt++;
fileHander->fileuuid = sectorHeaderInfo->fileuuid;
fileHander->sector_header = sectorHeaderInfo;
fileHander->file_offset = 0;
fileHander->file_size = 0;
fileHander->checksum = 0;
return fileHander->fd;
} else {
@ -119,6 +122,8 @@ int zeeprom_fs_open(uint8_t* filename, wrflag_t wrflag) {
fileHander->fd = fileHander->fd;
fileHander->sector_header = sectorHeaderInfo;
fileHander->file_size = sector_mgr_file_get_size(fileHander->fileuuid);
fileHander->checksum = sector_mgr_file_get_checksum(fileHander->fileuuid);
ZLOGI("filesize:%d", fileHander->file_size);
memcpy(fileHander->filename, filename, 8);
memcpy(fileHander->usrdata, sectorHeaderInfo->usrdata, sizeof(sectorHeaderInfo->usrdata));
sector_mgr_open_sector(fileHander->fileuuid);
@ -138,7 +143,7 @@ int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) {
zeeprom_sector_info_t* endsector = NULL;
int32_t wadd = 0;
ZASSERT(size == 256);
ZASSERT(size == EEPROM_SECTOR_MIN_WR_SIZE);
fileHander = filehandler_find(fileid);
if (!fileHander) {
@ -168,13 +173,15 @@ int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) {
ZLOGE("sector_mgr_get_sector_rom_add fail");
return -1;
}
ZASSERT(wadd % 256 == 0);
ZASSERT(wadd % EEPROM_SECTOR_MIN_WR_SIZE == 0);
ZASSERT(wadd >= EEPROM_SECTOR_SIZE);
zeeprom_write(wadd + endsector->datalen, data, size);
endsector->datalen = endsector->datalen + size;
endsector->sector_data_checksum += compute_checksum(data, size);
fileHander->file_offset += size;
fileHander->file_size += size;
fileHander->checksum += compute_checksum(data, size);
if (endsector->datalen == EEPROM_SECTOR_SIZE) {
zeeprom_sector_info_t* newsector = sector_mgr_force_find_idle_sector();
@ -184,8 +191,9 @@ int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) {
}
memset(newsector, 0, sizeof(zeeprom_sector_info_t));
newsector->usage = 1;
newsector->opened = 1;
newsector->usage = 1;
newsector->opened = 1;
newsector->sector_data_checksum = 0;
memcpy(newsector->filename, header_sinfo->filename, 8);
newsector->sector_index_in_file = endsector->sector_index_in_file + 1;
newsector->datalen = 0;
@ -204,8 +212,8 @@ int zeeprom_fs_close(int fileid) {
}
sector_mgr_close_sector(fileHander->fileuuid);
int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum));
m_eeprom_header.checksum = checksum_val;
uint32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.sector_info_headers_checksum));
m_eeprom_header.sector_info_headers_checksum = checksum_val;
// zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header));
filehandler_rlease(fileid);
@ -226,10 +234,14 @@ int zeeprom_fs_read(int fileid, uint8_t* data, int32_t size) {
* @brief
* ÕÒµ½µ±Ç°ÉÈÇø
*/
ZASSERT(size == 256);
ZASSERT(size == EEPROM_SECTOR_MIN_WR_SIZE);
filehandler_t* fileHander = filehandler_find(fileid);
if (!fileHander) return -1;
if (fileHander->file_offset + size > fileHander->file_size) {
return -1;
}
zeeprom_sector_info_t* header_sinfo = fileHander->sector_header;
if (!header_sinfo) {
return -1;
@ -244,7 +256,7 @@ int zeeprom_fs_read(int fileid, uint8_t* data, int32_t size) {
}
int32_t radd = sector_mgr_get_sector_rom_add(sector);
ZASSERT(radd % 256 == 0);
ZASSERT(radd % EEPROM_SECTOR_MIN_WR_SIZE == 0);
radd += sector_off;
zeeprom_read(radd, data, size);
@ -293,6 +305,11 @@ int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid) {
return sector_mgr_file_get_size(fileuuid);
}
int zeeprom_fs_get_checksum_by_fileuuid(int32_t fileuuid) {
ZASSERT(m_is_init);
return sector_mgr_file_get_checksum(fileuuid);
}
static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len) { //
int wrsize = EEPROM_SECTOR_MIN_WR_SIZE;
@ -323,8 +340,8 @@ static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len) {
}
}
static int32_t compute_checksum(uint8_t* data, uint16_t len) {
int32_t sum = 0;
static uint32_t compute_checksum(const uint8_t* data, uint16_t len) {
uint32_t sum = 0;
for (int i = 0; i < len; i++) {
sum += data[i];
}
@ -522,6 +539,18 @@ static int32_t sector_mgr_file_get_size(int32_t fileuuid) {
return filesize;
}
static int32_t sector_mgr_file_get_checksum(int32_t fileuuid) {
int32_t checksum = 0;
for (int i = 0; i < MAX_SECTOR_NUM; i++) {
zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i];
if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) {
checksum += sinfo->sector_data_checksum;
}
}
return checksum;
}
static const char* filename2str(uint8_t* filename) {
static char filename_str[32];
sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]);

60
app/src/zeeprom_fs.h

@ -1,5 +1,44 @@
#pragma once
#include <stdint.h>
/**
* @brief EEPROM简易文件系统代码框架
*
* [][]
*
* -----------------
* | |
* | | 8K * 1
* | |
* -----------------
* | |
* | N* | 8K * 31
* | |
* -----------------
*
* 31* zeeprom_sector_info_t个结构体
* :zeeprom_sector_info_t * 31
* uint8_t usage; // 0: 1:使
* uint8_t opened; // 0: 1:
* uint8_t filename[8]; //
* int32_t sector_index_in_file; //
* int32_t datalen; //
* uint32_t checksum; //
* int32_t fileuuid; // index判断文件创建的先后顺序
* uint8_t usrdata[20]; //
*
*
* :
* 1.8K,
* 2.fileuuid进行判定
* 3.fileuuid的所有zeeprom_sector_info_t.datalen的和即可
* 4.sector_index_in_file进行判断
* 5.sector_index_in_file为0的zeeprom_sector_info_t结构体中
*
* :
* 1.
* 2. flash中即可
*
*/
#define EEPROM_SIZE (256 * 1024)
#define EEPROM_SECTOR_MIN_WR_SIZE (256)
@ -10,13 +49,14 @@
//
#pragma pack(1)
typedef struct {
uint8_t usage;
uint8_t opened;
uint8_t filename[8]; //
int32_t sector_index_in_file; //
int32_t datalen; //
int32_t fileuuid; // index判断文件创建的先后顺序
uint8_t usrdata[20];
uint8_t usage;
uint8_t opened;
uint8_t filename[8]; //
int32_t sector_index_in_file; //
int32_t datalen; //
uint32_t sector_data_checksum; //
int32_t fileuuid; // index判断文件创建的先后顺序
uint8_t usrdata[20];
} zeeprom_sector_info_t;
typedef struct {
@ -26,6 +66,7 @@ typedef struct {
zeeprom_sector_info_t* sector_header;
int32_t file_offset;
int32_t file_size;
uint32_t checksum;
int fd;
int32_t fileuuid;
@ -33,8 +74,8 @@ typedef struct {
typedef struct {
zeeprom_sector_info_t sectorinfos[MAX_SECTOR_NUM];
int32_t fileuuid;
int32_t checksum;
int32_t fileuuid_cnt; // 使
uint32_t sector_info_headers_checksum; //
} zeeprom_header_t;
#pragma pack()
@ -64,3 +105,4 @@ int zeeprom_fs_delete_by_name(uint8_t* filename);
int zeeprom_fs_dump_sector_state();
int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid);
int zeeprom_fs_get_checksum_by_fileuuid(int32_t fileuuid);

2
ify_hrs_protocol

@ -1 +1 @@
Subproject commit f2eae40f67048820f37dc5dd3585ca9a75156dfc
Subproject commit 3a8a24c94c2e5f27b64a4488a9e6da3b61c7f0b0

2
libznordic

@ -1 +1 @@
Subproject commit 9f78147bbb47a49e378efcab6fd1c5f282931d7b
Subproject commit 2cd92d921156e9c84915520186fd611062537f65

16738
release/V9/one_lead_ecg_v9.hex
File diff suppressed because it is too large
View File

BIN
release/V9/one_lead_ecg_v9.zip

Loading…
Cancel
Save