mirror of
https://github.com/google/pebble.git
synced 2026-02-17 18:56:50 -05:00
Import of the watch repository from Pebble
This commit is contained in:
100
src/fw/drivers/flash/cd_flash_driver.c
Normal file
100
src/fw/drivers/flash/cd_flash_driver.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "drivers/flash.h"
|
||||
#include "drivers/flash/flash_impl.h"
|
||||
#include "drivers/watchdog.h"
|
||||
#include "flash_region/flash_region.h"
|
||||
#include "kernel/util/delay.h"
|
||||
|
||||
#include "kernel/core_dump_private.h"
|
||||
|
||||
//! We have our own flash driver for coredump support because it must not use
|
||||
//! any FreeRTOS constructs & we want to keep it as simple as possible. In
|
||||
//! addition we want the flexibility to be able to reset the flash driver to
|
||||
//! get it into a working state
|
||||
|
||||
void cd_flash_init(void) {
|
||||
// Reset & (re)initialize the flash HW
|
||||
flash_impl_init(true /* coredump_mode */);
|
||||
|
||||
// Protect the PRF region from writes
|
||||
flash_impl_write_protect(
|
||||
FLASH_REGION_SAFE_FIRMWARE_BEGIN,
|
||||
(FLASH_REGION_SAFE_FIRMWARE_END - SECTOR_SIZE_BYTES));
|
||||
}
|
||||
|
||||
void cd_flash_erase_region(uint32_t start_addr, uint32_t total_bytes) {
|
||||
CD_ASSERTN(((start_addr & SUBSECTOR_ADDR_MASK) == start_addr) &&
|
||||
((total_bytes & SUBSECTOR_ADDR_MASK) == total_bytes));
|
||||
|
||||
while (total_bytes > 0) {
|
||||
watchdog_feed();
|
||||
|
||||
uint32_t erase_size = 0;
|
||||
if (((start_addr & SECTOR_ADDR_MASK) == start_addr) &&
|
||||
(total_bytes >= SECTOR_SIZE_BYTES)) {
|
||||
erase_size = SECTOR_SIZE_BYTES;
|
||||
flash_impl_erase_sector_begin(start_addr);
|
||||
} else if ((start_addr & SUBSECTOR_ADDR_MASK) == start_addr &&
|
||||
(total_bytes >= SUBSECTOR_SIZE_BYTES)) {
|
||||
erase_size = SUBSECTOR_SIZE_BYTES;
|
||||
flash_impl_erase_subsector_begin(start_addr);
|
||||
} else {
|
||||
// Unaligned start address or unaligned erase size
|
||||
CD_ASSERTN(0);
|
||||
}
|
||||
|
||||
status_t status;
|
||||
while ((status = flash_impl_get_erase_status()) == E_BUSY) delay_us(100);
|
||||
CD_ASSERTN(status == S_SUCCESS);
|
||||
|
||||
total_bytes -= erase_size;
|
||||
start_addr += erase_size;
|
||||
}
|
||||
|
||||
watchdog_feed();
|
||||
}
|
||||
|
||||
uint32_t cd_flash_write_bytes(const void *buffer_ptr, uint32_t start_addr,
|
||||
const uint32_t buffer_size) {
|
||||
CD_ASSERTN(((start_addr + buffer_size) <= CORE_DUMP_FLASH_END) &&
|
||||
(int)start_addr >= CORE_DUMP_FLASH_START);
|
||||
|
||||
const uint8_t *buffer = buffer_ptr;
|
||||
uint32_t remaining = buffer_size;
|
||||
|
||||
while (remaining) {
|
||||
int written = flash_impl_write_page_begin(buffer, start_addr, remaining);
|
||||
CD_ASSERTN(PASSED(written));
|
||||
status_t status;
|
||||
while ((status = flash_impl_get_write_status()) == E_BUSY) {
|
||||
delay_us(10);
|
||||
}
|
||||
CD_ASSERTN(PASSED(status));
|
||||
buffer += written;
|
||||
start_addr += written;
|
||||
remaining -= written;
|
||||
}
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void cd_flash_read_bytes(void* buffer_ptr, uint32_t start_addr,
|
||||
uint32_t buffer_size) {
|
||||
flash_impl_read_sync(buffer_ptr, start_addr, buffer_size);
|
||||
}
|
||||
Reference in New Issue
Block a user