Skip to content

Commit

Permalink
Add support for external SPI flash.
Browse files Browse the repository at this point in the history
  • Loading branch information
tzarc committed Jun 26, 2022
1 parent 997534b commit f45effd
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
6 changes: 5 additions & 1 deletion builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ ifneq ($(strip $(FLASH_DRIVER)), none)
endif
endif

VALID_WEAR_LEVELING_DRIVER_TYPES := custom efl stm32f4x1
VALID_WEAR_LEVELING_DRIVER_TYPES := custom efl stm32f4x1 flash_spi
WEAR_LEVELING_DRIVER ?= none
ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none)
ifeq ($(filter $(WEAR_LEVELING_DRIVER),$(VALID_WEAR_LEVELING_DRIVER_TYPES)),)
Expand All @@ -277,6 +277,10 @@ ifneq ($(strip $(WEAR_LEVELING_DRIVER)),none)
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
SRC += flash_stm32.c wear_leveling_stm32f4x1.c
POST_CONFIG_H += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/wear_leveling/wear_leveling_stm32f4x1_config.h
else ifeq ($(strip $(WEAR_LEVELING_DRIVER)), flash_spi)
COMMON_VPATH += $(DRIVER_PATH)/flash
SRC += flash_spi.c wear_leveling_flash_spi.c
POST_CONFIG_H += $(DRIVER_PATH)/wear_leveling/wear_leveling_flash_spi_config.h
endif
endif
endif
Expand Down
60 changes: 60 additions & 0 deletions drivers/wear_leveling/wear_leveling_flash_spi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdbool.h>
#include <hal.h>
#include "timer.h"
#include "wear_leveling.h"
#include "wear_leveling_internal.h"

bool backing_store_init(void) {
bs_dprintf("Init\n");
flash_init();
return true;
}

bool backing_store_unlock(void) {
bs_dprintf("Unlock\n");
// No-op -- handled by the flash driver as it is.
return true;
}

bool backing_store_erase(void) {
#ifdef WEAR_LEVELING_DEBUG_OUTPUT
uint32_t start = timer_read32();
#endif

bool ret = true;
for (int i = 0; i < (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT); ++i) {
flash_status_t status = flash_erase_block(((WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) + i) * (EXTERNAL_FLASH_BLOCK_SIZE));
if (status != FLASH_STATUS_SUCCESS) {
ret = false;
break;
}
}

bs_dprintf("Backing store erase took %ldms to complete\n", ((long)(timer_read32() - start)));
return ret;
}

bool backing_store_write(uint32_t address, backing_store_int_t value) {
bs_dprintf("Write ");
uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
wl_dump(offset, &value, sizeof(value));
value = ~value;
return flash_write_block(offset, &value, sizeof(value)) == FLASH_STATUS_SUCCESS;
}

bool backing_store_lock(void) {
bs_dprintf("Lock \n");
// No-op -- handled by the flash driver as it is.
return true;
}

bool backing_store_read(uint32_t address, backing_store_int_t *value) {
bs_dprintf("Read ");
uint32_t offset = (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET) * (EXTERNAL_FLASH_BLOCK_SIZE) + address;
flash_status_t status = flash_read_block(offset, value, sizeof(backing_store_int_t));
*value = ~(*value);
wl_dump(offset, value, sizeof(backing_store_int_t));
return status == FLASH_STATUS_SUCCESS;
}
34 changes: 34 additions & 0 deletions drivers/wear_leveling/wear_leveling_flash_spi_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#ifndef __ASSEMBLER__
# include <stdlib.h>
# include <stdint.h>
# include "flash_spi.h"
#endif

// Use 1 block -- check the config for the SPI flash to determine how big it is
#ifndef WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT
# define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT 1
#endif // WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT

// Start at the first block of the external flash
#ifndef WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET
# define WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET 0
#endif // WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_OFFSET

// 8-byte writes by default
#ifndef BACKING_STORE_WRITE_SIZE
# define BACKING_STORE_WRITE_SIZE 8
#endif

// The space allocated by the block
#ifndef WEAR_LEVELING_BACKING_SIZE
# define WEAR_LEVELING_BACKING_SIZE ((EXTERNAL_FLASH_BLOCK_SIZE) * (WEAR_LEVELING_EXTERNAL_FLASH_BLOCK_COUNT))
#endif // WEAR_LEVELING_BACKING_SIZE

// Use half of the backing size for logical EEPROM
#ifndef WEAR_LEVELING_LOGICAL_SIZE
# define WEAR_LEVELING_LOGICAL_SIZE ((WEAR_LEVELING_BACKING_SIZE) / 2)
#endif // WEAR_LEVELING_LOGICAL_SIZE
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ bool backing_store_read(uint32_t address, backing_store_int_t *value) {
backing_store_int_t *loc = (backing_store_int_t *)offset;
*value = ~(*loc);
bs_dprintf("Read ");
wl_dump(offset, loc, sizeof(value));
wl_dump(offset, loc, sizeof(backing_store_int_t));
return true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ bool backing_store_read(uint32_t address, backing_store_int_t* value) {
backing_store_int_t* loc = (backing_store_int_t*)offset;
*value = ~(*loc);
bs_dprintf("Read ");
wl_dump(offset, loc, 2);
wl_dump(offset, loc, sizeof(backing_store_int_t));
return true;
}

0 comments on commit f45effd

Please sign in to comment.