mirror of
https://github.com/google/pebble.git
synced 2025-03-16 17:11:21 +00:00
77 lines
3 KiB
C
77 lines
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.
|
|
*/
|
|
|
|
#include "drivers/flash.h"
|
|
#include "flash_region/flash_region.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
static void prv_erase_optimal_range(uint32_t min_start, uint32_t max_start,
|
|
uint32_t min_end, uint32_t max_end) {
|
|
// We want to erase the sector that starts immediately below max_start but after min_start. If no sector
|
|
// boundary exists between the two, we need to start erasing sectors after min_start and backfill with
|
|
// subsector erases.
|
|
int32_t sector_start = (max_start & SECTOR_ADDR_MASK);
|
|
int32_t subsector_start = (max_start & SUBSECTOR_ADDR_MASK);
|
|
if (sector_start < (int32_t) min_start) {
|
|
sector_start += SECTOR_SIZE_BYTES;
|
|
}
|
|
|
|
// We want to erase ending after min_end but before max_end. If that ends running past the end of max_end,
|
|
// we need to erase starting with the sector before and fill in with subsector erases.
|
|
int32_t sector_end = ((min_end - 1) & SECTOR_ADDR_MASK) + SECTOR_SIZE_BYTES;
|
|
int32_t subsector_end = ((min_end - 1) & SUBSECTOR_ADDR_MASK) + SUBSECTOR_SIZE_BYTES;
|
|
if (sector_end > (int32_t) max_end) {
|
|
sector_end -= SECTOR_SIZE_BYTES;
|
|
}
|
|
|
|
int erase_count = 0;
|
|
|
|
// Do the upkeep immediately just in case we've spent awhile running without feeding the
|
|
// watchdog before doing this erase operation.
|
|
|
|
if (sector_start < sector_end) {
|
|
// Now erase the leading subsectors...
|
|
for (int32_t i = subsector_start; i < sector_start; i += SUBSECTOR_SIZE_BYTES) {
|
|
flash_erase_subsector_blocking(i);
|
|
}
|
|
|
|
// Erase the full sectors...
|
|
for (int32_t i = sector_start; i < sector_end; i += SECTOR_SIZE_BYTES) {
|
|
flash_erase_sector_blocking(i);
|
|
}
|
|
|
|
// Erase the trailing subsectors
|
|
for (int32_t i = sector_end; i < subsector_end; i += SUBSECTOR_SIZE_BYTES) {
|
|
flash_erase_subsector_blocking(i);
|
|
}
|
|
} else {
|
|
// Can't erase any full sectors, just erase subsectors the whole way.
|
|
for (int32_t i = subsector_start; i < subsector_end; i += SUBSECTOR_SIZE_BYTES) {
|
|
flash_erase_subsector_blocking(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void flash_region_erase_optimal_range(uint32_t min_start, uint32_t max_start,
|
|
uint32_t min_end, uint32_t max_end) {
|
|
prv_erase_optimal_range(min_start, max_start, min_end, max_end);
|
|
}
|
|
|
|
void flash_region_erase_optimal_range_no_watchdog(uint32_t min_start, uint32_t max_start,
|
|
uint32_t min_end, uint32_t max_end) {
|
|
prv_erase_optimal_range(min_start, max_start, min_end, max_end);
|
|
}
|