/**************************************************************************//** * @brief Writes data after the last occupied location and returns the updated * value for the last occupied location * * @param data is the pointer to the data that will be written to the flash * @param length is the length of the data that will be written to the flash * * @return \b flash_write_count is the last occupied location ******************************************************************************/ unsigned int flash_write_wear_level(unsigned int *data, unsigned int length) { unsigned int ii, index; unsigned int flash_write_count; flash_read_data(&flash_write_count, 0 ,1); switch(flash_write_count){ // the case of a un-initialized array, brandnew device case 0xFFFF: flash_write_count = 1; flash_write_data(&flash_write_count, 0 ,1); flash_write_data(data, 1 ,length); break; // the case of having reached 50000 writes, reset the counter to 1 case 0xC350: flash_write_count = 1; flash_erase_segment(0, SIZE_OF_STORAGE_ARRAY); flash_write_data(&flash_write_count, 0 ,1); flash_write_data(data, 1 ,length); break; // Normal operation, find the end of the current array, store new data default: // search the array for the end of the flash storage array, look for 0xFFFF for(ii=0;ii<SIZE_OF_STORAGE_ARRAY;ii=ii+length+1) { flash_read_data(&flash_write_count, ii ,1); if(flash_write_count == 0xFFFF) { flash_read_data(&flash_write_count, 0 ,1); index = ii; ii = SIZE_OF_STORAGE_ARRAY; } } // before writing to segment, check to see if we are out of bound if(index+length+1 > SIZE_OF_STORAGE_ARRAY ) { // if we have reached the end, delete the entire array, increment counter and restart flash_read_data(&flash_write_count, 0 ,1); flash_erase_segment(0, SIZE_OF_STORAGE_ARRAY); flash_write_count++; flash_write_data(&flash_write_count, 0 ,1); flash_write_data(data, 1 ,length); } else { // Normal write to Flash array flash_write_data(&flash_write_count, index ,1); flash_write_data(data, index+1 ,length); } break; } return flash_write_count; }
// ************************************************************************************************* // @fn db_clear // @brief Clear the dataabase // @param none // @return none // ************************************************************************************************* void db_clear(void) { u8 i; for (i = 0; i < MAX_TABLES; ++i) { memset(&tables[i], 0, sizeof(db_table_t)); flash_erase_segment((u8*)tables_in_flash[i]); } memset(&info, 0, sizeof(db_info_t)); flash_erase_segment((u8*)info_in_flash); }
// ************************************************************************************************* // @fn db_save // @brief save a encryption key for a door // @param id, key // @return status, 0 = success, 1 = db full // ************************************************************************************************* u8 db_save(u16 id, u8 key[16]) { u8 i, j; u8 empty_found = 0, empty_i = 0, empty_j = 0; // first find if the record already exists for (i = 0; i < MAX_TABLES; ++i) { for (j = 0; j < RECORDS_PER_TABLE; ++j) { if (tables[i].records[j].id == id) { // found it // erase flash_erase_segment((u8*)tables_in_flash[i]); // update RAM first memcpy(tables[i].records[j].key, key, 16); // calculat new crc tables[i].crc = crc_compute((u8*)&tables[i], RECORDS_PER_TABLE * sizeof(db_record_t)); // write only one segment flash_write_segment((u8*)tables_in_flash[i], (u8*)(&tables[i])); return 0; } else if (!empty_found && !tables[i].records[j].id) { empty_i = i; empty_j = j; empty_found = 1; } } } // is database all full? if (!empty_found) return 1; // erase flash_erase_segment((u8*)tables_in_flash[empty_i]); // write to a new slot tables[empty_i].records[empty_j].id = id; memcpy(tables[empty_i].records[empty_j].key, key, 16); // calculat new crc tables[empty_i].crc = crc_compute((u8*)&tables[empty_i], RECORDS_PER_TABLE * sizeof(db_record_t)); // write only one segment flash_write_segment((u8*)tables_in_flash[empty_i], (u8*)(&tables[empty_i])); return 0; }
/* returns 1 if the id was expected and set, 0 otherwise */ static void set_node_id(unsigned char id) { TIMER_ID_INPUT = UINT_MAX; if(flash_write_byte((unsigned char *) NODE_ID_LOCATION, id) != 0) { flash_erase_segment((unsigned int *) NODE_ID_LOCATION); flash_write_byte((unsigned char *) NODE_ID_LOCATION, id); } node_id = id; printf("this node id is now 0x%02X\r\n", id); }
u16 db_id(void) { if (info.id && info.id != 0xFFFFu) return info.id; info.id = 0; while (!info.id || info.id == 0xFFFFu) { info.id ^= TA0R; info.id ^= crc_compute((u8*)&sDate, sizeof(struct date)); info.id ^= crc_compute((u8*)&sTime, sizeof(struct time)); info.id ^= crc_compute((u8*)&sBatt, sizeof(struct batt)); } flash_erase_segment((u8*)info_in_flash); info.crc = crc_compute((u8*)&info, sizeof(db_info_t) - 2); flash_write_segment((u8*)info_in_flash, (u8*)(&info)); return info.id; }