int logging_flash_init_state()

in core/logging/logging_flash.c [346:469]


int logging_flash_init_state (const struct logging_flash *logging)
{
	int curr_sector_num;
	uint8_t *pos;
	uint8_t *end;
	uint32_t entry_id = 0;
	uint32_t prev_entry_id = 0;
	uint32_t flash_addr;
	int found_next = 0;
	int status;

	if ((logging == NULL) || (logging->state == NULL) || (logging->flash == NULL)) {
		return LOGGING_INVALID_ARGUMENT;
	}

	if (FLASH_BLOCK_BASE (logging->base_addr) != logging->base_addr) {
		return LOGGING_STORAGE_NOT_ALIGNED;
	}

	memset (logging->state, 0, sizeof (struct logging_flash_state));

	flash_addr = logging->base_addr;
	end = logging->state->entry_buffer + sizeof (logging->state->entry_buffer);

	for (curr_sector_num = 0; curr_sector_num < LOGGING_FLASH_SECTORS; ++curr_sector_num) {
		status = spi_flash_read (logging->flash,
			logging->base_addr + (FLASH_SECTOR_SIZE * curr_sector_num),
			logging->state->entry_buffer, sizeof (logging->state->entry_buffer));
		if (status != 0) {
			return status;
		}

		pos = logging->state->entry_buffer;
		while ((end - pos) >= (int) sizeof (struct logging_entry_header)) {
			struct logging_entry_header *header = (struct logging_entry_header*) pos;

			if (!LOGGING_IS_ENTRY_START (header->log_magic) ||
				(LOGGING_HEADER_FORMAT (header->log_magic) == 0xA)) {
				if (found_next == 0) {
					if (FLASH_SECTOR_OFFSET (flash_addr) == 0) {
						found_next = 1;
					}
					else {
						bool blank = true;

						while (pos != end) {
							if (*pos != 0xff) {
								blank = false;
								break;
							}

							pos++;
						}

						if (!blank) {
							flash_addr = FLASH_SECTOR_BASE (flash_addr) + FLASH_SECTOR_SIZE;
						}
						else {
							found_next = 1;
						}
					}
				}
				break;
			}
			else {
				int length = header->length & ~LOGGING_FLASH_TERMINATOR;

				if ((length > (end - pos)) ||
					(length < (int) sizeof (struct logging_entry_header))) {
					if (found_next == 0) {
						flash_addr = FLASH_SECTOR_BASE (flash_addr) + FLASH_SECTOR_SIZE;
					}
					break;
				}

				if (header->length & LOGGING_FLASH_TERMINATOR) {
					if (found_next == 0) {
						flash_addr = FLASH_SECTOR_BASE (flash_addr) + FLASH_SECTOR_SIZE;
					}
					break;
				}

				if (found_next < 2) {
					entry_id = header->entry_id + 1;

					if (prev_entry_id > entry_id) {
						entry_id = prev_entry_id;
						logging->state->log_start = curr_sector_num;
						found_next = 2;
					}
					else if (found_next == 0) {
						flash_addr += length;
						prev_entry_id = entry_id;
					}
				}

				logging->state->flash_used[curr_sector_num] += length;
				pos += length;
			}
		}

		if ((FLASH_SECTOR_SIZE - FLASH_SECTOR_OFFSET (flash_addr)) <
			sizeof (struct logging_entry_header)) {
			flash_addr = FLASH_SECTOR_BASE (flash_addr) + FLASH_SECTOR_SIZE;
		}
	}

	if (flash_addr >= (logging->base_addr + LOGGING_FLASH_AREA_LEN)) {
		flash_addr = logging->base_addr;
	}

	status = platform_mutex_init (&logging->state->lock);
	if (status != 0) {
		return status;
	}

	logging->state->next_addr = flash_addr;
	logging->state->next_entry_id = entry_id;
	logging->state->next_write = logging->state->entry_buffer;
	logging->state->write_remain =
		sizeof (logging->state->entry_buffer) - FLASH_SECTOR_OFFSET (flash_addr);

	return 0;
}