mirror of
https://github.com/google/pebble.git
synced 2025-06-03 16:53:11 +00:00
210 lines
7.3 KiB
C
210 lines
7.3 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "system/status_codes.h"
|
|
|
|
static const uint32_t EXPECTED_SPI_FLASH_ID_32MBIT = 0x20bb16;
|
|
static const uint32_t EXPECTED_SPI_FLASH_ID_64MBIT = 0x20bb17;
|
|
|
|
/**
|
|
* Configure the micro's peripherals to communicate with the flash
|
|
* chip.
|
|
*/
|
|
void flash_init(void);
|
|
|
|
//! Stop all flash transactions.
|
|
void flash_stop(void);
|
|
|
|
/**
|
|
* Retreieve the first 3 bytes of the flash's device id. This ID
|
|
* should remain fixed across all chips.
|
|
*/
|
|
uint32_t flash_whoami(void);
|
|
|
|
/**
|
|
* Read 1 or more bytes starting at the specified 24bit address into
|
|
* the provided buffer. This function does no range checking, so it is
|
|
* currently possible to run off the end of the flash.
|
|
*
|
|
* @param buffer A byte-buffer that will be used to store the data
|
|
* read from flash.
|
|
* @param start_addr The address of the first byte to be read from flash.
|
|
* @param buffer_size The total number of bytes to be read from flash.
|
|
*/
|
|
void flash_read_bytes(uint8_t* buffer, uint32_t start_addr, uint32_t buffer_size);
|
|
|
|
/**
|
|
* Write 1 or more bytes from the buffer to flash starting at the
|
|
* specified 24bit address. This function will handle both writing a
|
|
* buffer that is larger than the flash's page size and writing to a
|
|
* non-page aligned address.
|
|
*
|
|
* @param buffer A byte-buffer containing the data to be written to flash.
|
|
* @param start_addr The address of the first byte to be written to flash.
|
|
* @param buffer_size The total number of bytes to be written.
|
|
*/
|
|
void flash_write_bytes(const uint8_t* buffer, uint32_t start_addr, uint32_t buffer_size);
|
|
|
|
typedef void (*FlashOperationCompleteCb)(void *context, status_t result);
|
|
|
|
/**
|
|
* Erase a subsector asynchronously.
|
|
*
|
|
* The callback function will be called when the erase completes, whether the
|
|
* erase succeeded or failed. The callback will be executed on an arbitrary
|
|
* (possibly high-priority) task, so the callback function must return quickly.
|
|
* The callback may also be called directly from within flash_erase_subsector.
|
|
*/
|
|
void flash_erase_subsector(uint32_t subsector_addr,
|
|
FlashOperationCompleteCb on_complete,
|
|
void *context);
|
|
|
|
/**
|
|
* Erase a sector asynchronously.
|
|
*
|
|
* The callback function will be called when the erase completes, whether the
|
|
* erase succeeded or failed. The callback will be executed on an arbitrary
|
|
* (possibly high-priority) task, so the callback function must return quickly.
|
|
* The callback may also be called directly from within flash_erase_sector.
|
|
*/
|
|
void flash_erase_sector(uint32_t sector_addr,
|
|
FlashOperationCompleteCb on_complete,
|
|
void *context);
|
|
|
|
/**
|
|
* Erase the subsector containing the specified address.
|
|
*/
|
|
void flash_erase_subsector_blocking(uint32_t subsector_addr);
|
|
|
|
/**
|
|
* Erase the sector containing the specified address.
|
|
*
|
|
* Beware: this function takes 100ms+ to execute, so be careful when you call it.
|
|
*/
|
|
void flash_erase_sector_blocking(uint32_t sector_addr);
|
|
|
|
/**
|
|
* Check whether the sector containing the specified address is already erased.
|
|
*/
|
|
bool flash_sector_is_erased(uint32_t sector_addr);
|
|
|
|
/**
|
|
* Check whether the subsector containing the specified address is already erased.
|
|
*/
|
|
bool flash_subsector_is_erased(uint32_t sector_addr);
|
|
|
|
/**
|
|
* Erase the entire contents of flash.
|
|
*
|
|
* Note: This is a very slow (up to a minute) blocking operation. Don't let the watchdog kill
|
|
* you when calling this.
|
|
*/
|
|
void flash_erase_bulk(void);
|
|
|
|
/**
|
|
* Erase a region of flash asynchronously using as few erase operations as
|
|
* possible.
|
|
*
|
|
* At least (max_start, min_end) but no more than (min_start, max_end) will be
|
|
* erased. Both min_start and max_end must be aligned to a subsector address as
|
|
* that is the smallest unit that can be erased.
|
|
*/
|
|
void flash_erase_optimal_range(
|
|
uint32_t min_start, uint32_t max_start, uint32_t min_end, uint32_t max_end,
|
|
FlashOperationCompleteCb on_complete, void *context);
|
|
|
|
/**
|
|
* Configure the flash driver to enter a deep sleep mode between commands.
|
|
*/
|
|
void flash_sleep_when_idle(bool enable);
|
|
|
|
//! @return True if sleeping when idle is currently enabled.
|
|
bool flash_get_sleep_when_idle(void);
|
|
|
|
void debug_flash_dump_registers(void);
|
|
|
|
//! @return true if the flash peripheral has been initialized.
|
|
bool flash_is_initialized(void);
|
|
|
|
//! Helper function to check that the Flash ID (whoami) is correct
|
|
//! @return true if the flash ID matches what we expect based on the board config
|
|
bool flash_is_whoami_correct(void);
|
|
|
|
//! Helper function to extract the Flash Size from the ID (whoami)
|
|
//! @return the size of the flash in bytes
|
|
size_t flash_get_size(void);
|
|
|
|
// This is only intended to be called when entering stop mode. It does not use
|
|
// any locks because IRQs have already been disabled. The idea is to only incur
|
|
// the wait penalty for entering/exiting deep sleep mode for the flash
|
|
// before/after stop mode. The flash part consumes ~100uA in standby mode and
|
|
// ~10uA when its in deep sleep mode. If the MCU is not in stop mode, this
|
|
// difference is negligible
|
|
void flash_power_down_for_stop_mode(void);
|
|
void flash_power_up_after_stop_mode(void);
|
|
|
|
typedef enum {
|
|
FLASH_MODE_ASYNC = 0,
|
|
FLASH_MODE_SYNC_BURST,
|
|
|
|
// Add new modes above this
|
|
FLASH_MODE_NUM_MODES
|
|
}FlashModeType;
|
|
|
|
/**
|
|
* Manually switches modes between asynchronous/synchronous
|
|
*
|
|
*/
|
|
void flash_switch_mode(FlashModeType mode);
|
|
|
|
// Returns the sector address that the given flash address lies in
|
|
uint32_t flash_get_sector_base_address(uint32_t flash_addr);
|
|
|
|
// Returns the subsector address that the given flash address lies in
|
|
uint32_t flash_get_subsector_base_address(uint32_t flash_addr);
|
|
|
|
// Enable write protection on flash
|
|
void flash_enable_write_protection(void);
|
|
|
|
// Write-protects the prf region of flash
|
|
void flash_prf_set_protection(bool do_protect);
|
|
|
|
//! Compute a CRC32 checksum of a region of flash.
|
|
uint32_t flash_crc32(uint32_t flash_addr, uint32_t length);
|
|
|
|
//! Apply the legacy defective checksum to a region of flash.
|
|
uint32_t flash_calculate_legacy_defective_checksum(uint32_t flash_addr,
|
|
uint32_t length);
|
|
|
|
//! Call this before any external flash access (including memory-mapped)
|
|
//! to power on the flash peripheral if it wasn't already, and
|
|
//! to increase the internal reference counter that prevents flash peripheral from powering down.
|
|
void flash_use(void);
|
|
|
|
//! Convenience for \ref flash_release_many(1)
|
|
void flash_release(void);
|
|
|
|
//! Call this after you finished accessing external flash
|
|
//! to decrease the internal reference counter by num_locks, and
|
|
//! to turn off the flash peripheral if the reference counter reaches 0
|
|
//! param num_locks usually 1, the amount by which the reference counter should be decremented
|
|
void flash_release_many(uint32_t num_locks);
|