Add external memory support for cypress platform
Signed-off-by: Bohdan Kovalchuk <bohd@cypress.com> Signed-off-by: Roman Okhrimenko <roman.okhrimenko@cypress.com>
This commit is contained in:
parent
50d24a5751
commit
0324f1b023
|
@ -34,6 +34,10 @@ IMG_TYPE ?= BOOT
|
|||
# image type can be BOOT or UPGRADE
|
||||
IMG_TYPES = BOOT UPGRADE
|
||||
|
||||
# possible values are 0 and 0xff
|
||||
# internal Flash by default
|
||||
ERASED_VALUE ?= 0
|
||||
|
||||
ifneq ($(COMPILER), GCC_ARM)
|
||||
$(error Only GCC ARM is supported at this moment)
|
||||
endif
|
||||
|
@ -53,8 +57,8 @@ endif
|
|||
|
||||
# Define start of application, RAM start and size, slot size
|
||||
ifeq ($(PLATFORM), PSOC_062_2M)
|
||||
DEFINES_APP += -DRAM_START=0x08000000
|
||||
DEFINES_APP += -DRAM_SIZE=0x20000
|
||||
DEFINES_APP += -DRAM_START=0x08040000
|
||||
DEFINES_APP += -DRAM_SIZE=0x10000
|
||||
DEFINES_APP += -DUSER_APP_START=0x10018000
|
||||
SLOT_SIZE ?= 0x10000
|
||||
endif
|
||||
|
@ -80,7 +84,7 @@ ASM_FILES_APP :=
|
|||
# We still need this for MCUBoot apps signing
|
||||
IMGTOOL_PATH ?= ../../scripts/imgtool.py
|
||||
|
||||
SIGN_ARGS := sign --header-size 1024 --pad-header --align 8 -v "2.0" -S $(SLOT_SIZE) -M 512 --overwrite-only -R 0 -k keys/$(SIGN_KEY_FILE).pem
|
||||
SIGN_ARGS := sign --header-size 1024 --pad-header --align 8 -v "2.0" -S $(SLOT_SIZE) -M 512 --overwrite-only -R $(ERASED_VALUE) -k keys/$(SIGN_KEY_FILE).pem
|
||||
|
||||
# Output folder
|
||||
OUT := $(APP_NAME)/out
|
||||
|
|
|
@ -48,7 +48,7 @@ endif
|
|||
# NOTE: Absolute pathes for now for the sake of development
|
||||
ifeq ($(HOST_OS), win)
|
||||
ifeq ($(COMPILER), GCC_ARM)
|
||||
TOOLCHAIN_PATH ?= c:/Users/$(USERNAME)/ModusToolbox_1.0/tools/gcc-7.2.1-1.0
|
||||
TOOLCHAIN_PATH ?= c:/Users/$(USERNAME)/ModusToolbox/tools_2.1/gcc-7.2.1
|
||||
MY_TOOLCHAIN_PATH:=$(subst \,/,$(TOOLCHAIN_PATH))
|
||||
TOOLCHAIN_PATH := $(MY_TOOLCHAIN_PATH)
|
||||
GCC_PATH := $(TOOLCHAIN_PATH)
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
### External Memory support for Secondary Slot
|
||||
|
||||
**Description**
|
||||
|
||||
Given document describes the use of external memory module as a secondary (upgrade) slot with Cypress' PSoC6 devices.
|
||||
|
||||
The demonstration device is CY8CPROTO-062-4343W board which is PSoC6 device with 2M of Flash available.
|
||||
The memory module present on board is S25FL512SAGMFI010 512-Mbit external Quad SPI NOR Flash.
|
||||
|
||||
Using external memory for secondary slot allows to nearly double the size of Boot Image.
|
||||
|
||||
**Operation Design and Flow**
|
||||
|
||||
The design is based on using SFDP command's auto-discovery functionality of memory module IC and Cypress' SMIF PDL driver.
|
||||
|
||||
It is assumed that user's design meets following:
|
||||
* The memory-module used is SFDP-compliant;
|
||||
* There only one module is being used for secondary slot;
|
||||
* Only "OWERWRITE" bootloading scheme is used;
|
||||
* The address for secondary slot should start from 0x18000000.
|
||||
This corresponds to PSoC6's SMIF (Serial Memory InterFace) IP block mapping.
|
||||
* The slot size for upgrade slot is even (or smaller) to erase size (0x40000) of given memory module.
|
||||
This requirement is accepted for code simplicity.
|
||||
|
||||
The default flash map implemented is the following:
|
||||
* [0x10000000, 0x10018000] - MCUBootApp (bootloader) area;
|
||||
* [0x10018000, 0x10028000] - primary slot for BlinkyApp;
|
||||
* [0x18000000, 0x18010000] - secondary slot for BlinkyApp;
|
||||
* [0x10038000, 0x10039000] - scratch area (not used);
|
||||
|
||||
Size of slots `0x10000` - 64kB
|
||||
|
||||
**Note 1**: make sure primary, secondary slot and bootloader app sizes are appropriate and correspond to flash area size defined in Applications' linker files.
|
||||
|
||||
**Note 2**: make sure secondary slot start address is aligned (or smaller) to erase size (0x40000 - 256kB).
|
||||
|
||||
MCUBootApp's `main.c` contains the call to Init-SFDP API which performs required GPIO configurations, SMIF IP block configurations, SFDP protocol read and memory-config structure initialization.
|
||||
|
||||
After that MCUBootApp is ready to accept upgrade image from external memory module.
|
||||
|
||||
Once valid upgrade image was accepted the image in external memory will be erased.
|
||||
|
||||
**How to enable external memory support:**
|
||||
|
||||
1. Seek for `CY_BOOT_USE_EXTERNAL_FLASH` in sources and define it in any: MCUBootApp.mk or any suitable header file.
|
||||
2. Navigate to `cy_flash_map.c` and check if secondary slot start address and size meet the application's needs.
|
||||
3. Define which slave select is used for external memory on a board by setting `smif_id` value in `main.c`.
|
||||
4. Build MCUBootApp as described in `Readme.md`.
|
||||
|
||||
**How to build upgrade image for external memory:**
|
||||
|
||||
make app APP_NAME=BlinkyApp PLATFORM=PSOC_062_2M IMG_TYPE=UPGRADE HEADER_OFFSET=0x7FE8000 ERASED_VALUE=0xff
|
||||
|
||||
`HEADER_OFFSET` defines the offset from original boot image address. This one in line above suggests secondary slot will start from `0x18000000`.
|
||||
|
||||
`ERASED_VALUE` defines the memory cell contents in erased state. It is `0x00` for PSoC6's internal Flash and `0xff` for S25FL512S.
|
||||
|
||||
**Programming to external memory**
|
||||
|
||||
The MCUBootApp programming can be done similarly to described in `Readme.md`:
|
||||
|
||||
export OPENOCD=/Applications/ModusToolbox/tools_2.1/openocd
|
||||
|
||||
${OPENOCD}/bin/openocd -s ${OPENOCD}/scripts \
|
||||
-f ${OPENOCD}/scripts/interface/kitprog3.cfg \
|
||||
-f ${OPENOCD}/scripts/target/psoc6_2m.cfg \
|
||||
-c "init; psoc6 sflash_restrictions 1" \
|
||||
-c "init; reset init; program PATH_TO_APPLICATION.hex" \
|
||||
-c "resume; reset; exit"
|
||||
|
||||
There is a NULL-pointer placed for SMIF configuration pointer in TOC2 (Table Of Contents, `cy_serial_flash_prog.c`).
|
||||
This is done to force CY8PROTO-062-4343W DAP Link firmware to program external memory with hardcoded values.
|
||||
|
||||
1. Press SW3 Mode button on a board to switch the board into DAP Link mode.
|
||||
2. Once DAP Link removable disk appeared drop (copy) the upgrade image HEX file to it.
|
||||
This will invoke firmware to program external memory.
|
||||
|
||||
**Note 3:** the programming of external memory is limited to S25FL512S p/n only at this moment.
|
|
@ -63,7 +63,7 @@ MEMORY
|
|||
* Your changes must be aligned with the corresponding memory regions for the CM4 core in 'xx_cm4_dual.ld',
|
||||
* where 'xx' is the device group; for example, 'cy8c6xx7_cm4_dual.ld'.
|
||||
*/
|
||||
ram (rwx) : ORIGIN = 0x08000000, LENGTH = 0x20000
|
||||
ram (rwx) : ORIGIN = 0x08020000, LENGTH = 0x20000
|
||||
flash (rx) : ORIGIN = 0x10000000, LENGTH = 0x18000
|
||||
|
||||
/* This is a 32K flash region used for EEPROM emulation. This region can also be used as the general purpose flash.
|
||||
|
|
|
@ -45,6 +45,7 @@ DEFINES_APP := -DMBEDTLS_CONFIG_FILE="\"mcuboot_crypto_config.h\""
|
|||
DEFINES_APP += -DECC256_KEY_FILE="\"keys/$(SIGN_KEY_FILE).pub\""
|
||||
DEFINES_APP += -DCORE=$(CORE)
|
||||
DEFINES_APP += -DMCUBOOT_IMAGE_NUMBER=$(MCUBOOT_IMAGE_NUMBER)
|
||||
DEFINES_APP += -DCY_BOOT_USE_EXTERNAL_FLASH
|
||||
|
||||
ifeq ($(USE_CRYPTO_HW), 1)
|
||||
DEFINES_APP += -DMBEDTLS_USER_CONFIG_FILE="\"mcuboot_crypto_acc_config.h\""
|
||||
|
@ -53,8 +54,10 @@ endif
|
|||
SOURCES_MCUBOOT := $(wildcard $(CURDIR)/../bootutil/src/*.c)
|
||||
# Collect MCUBoot Application sources
|
||||
SOURCES_APP_SRC := $(wildcard $(CUR_APP_PATH)/*.c)
|
||||
|
||||
# Collect Flash Layer port sources
|
||||
SOURCES_FLASH_PORT := $(wildcard $(CURDIR)/cy_flash_pal/*.c)
|
||||
SOURCES_FLASH_PORT += $(wildcard $(CURDIR)/cy_flash_pal/flash_qspi/*.c)
|
||||
# Collect all the sources
|
||||
SOURCES_APP := $(SOURCES_MCUBOOT)
|
||||
SOURCES_APP += $(SOURCES_APP_SRC)
|
||||
|
@ -65,6 +68,7 @@ INCLUDE_DIRS_MCUBOOT += $(addprefix -I, $(CURDIR)/../bootutil/src)
|
|||
INCLUDE_DIRS_MCUBOOT += $(addprefix -I, $(CURDIR)/..)
|
||||
|
||||
INCLUDE_DIRS_APP := $(addprefix -I, $(CURDIR))
|
||||
INCLUDE_DIRS_APP += $(addprefix -I, $(CURDIR)/cy_flash_pal/flash_qspi)
|
||||
INCLUDE_DIRS_APP += $(addprefix -I, $(CURDIR)/cy_flash_pal/include)
|
||||
INCLUDE_DIRS_APP += $(addprefix -I, $(CURDIR)/cy_flash_pal/include/flash_map_backend)
|
||||
INCLUDE_DIRS_APP += $(addprefix -I, $(CUR_APP_PATH))
|
||||
|
|
|
@ -94,4 +94,6 @@ int sim_log_enabled(int level);
|
|||
#define MCUBOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define MCUBOOT_LOG_MODULE_DECLARE(...)
|
||||
|
||||
#endif /* MCUBOOT_LOGGING_H */
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/***************************************************************************//**
|
||||
* \file cy_serial_flash_prog.c
|
||||
*
|
||||
* \brief
|
||||
* Provides variables necessary to inform programming tools how to program the
|
||||
* attached serial flash memory. The variables used here must be placed at
|
||||
* specific locations in order to be detected and used by programming tools
|
||||
* to know that there is an attached memory and its characteristics. Uses the
|
||||
* configuration provided as part of BSP.
|
||||
*
|
||||
********************************************************************************
|
||||
* \copyright
|
||||
* Copyright 2018-2019 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* \addtogroup group_serial_flash Serial Flash
|
||||
* \{
|
||||
* Variables for informing programming tools that there is an attached memory device and what
|
||||
* its characteristics are so it can be programmed just like the on-chip memory.
|
||||
*
|
||||
* \defgroup group_serial_flash_variables Variables
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "flash_qspi.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const cy_stc_smif_block_config_t * smifCfg; /* Pointer to SMIF top-level configuration */
|
||||
const uint32_t null_t; /* NULL termination */
|
||||
} stc_smif_ipblocks_arr_t;
|
||||
|
||||
/**
|
||||
* \addtogroup group_serial_flash_variables
|
||||
* \{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This data can be placed anywhere in the internal memory, but it must be at a location that
|
||||
* can be determined and used for the calculation of the CRC16 checksum in the cyToc below. There
|
||||
* are multiple ways this can be accomplished including:
|
||||
* 1) Placing it in a dedicated memory block with a known address. (as done here)
|
||||
* 2) Placing it at an absolute location via a the linker script
|
||||
* 3) Using 'cymcuelftool -S' to recompute the checksum and patch the elf file after linking
|
||||
*/
|
||||
CY_SECTION(".cy_sflash_user_data") __attribute__( (used) )
|
||||
/* const stc_smif_ipblocks_arr_t smifIpBlocksArr = {&smifBlockConfig_sfdp, 0x00000000}; */
|
||||
/* if used zero-pointer to config, DAP link will use hardcoded config for CY8CPROTO-062-4343W */
|
||||
const stc_smif_ipblocks_arr_t smifIpBlocksArr = {0x00000000, 0x00000000};
|
||||
|
||||
/**
|
||||
* This data is used to populate the table of contents part 2. When present, it is used by the boot
|
||||
* process and programming tools to determine key characteristics about the memory usage including
|
||||
* where the boot process should start the application from and what external memories are connected
|
||||
* (if any). This must consume a full row of flash memory row. The last entry is a checksum of the
|
||||
* other values in the ToC which must be updated if any other value changes. This can be done manually
|
||||
* or by running 'cymcuelftool -S' to recompute the checksum.
|
||||
*/
|
||||
CY_SECTION(".cy_toc_part2") __attribute__( (used) )
|
||||
const uint32_t cyToc[128] =
|
||||
{
|
||||
0x200-4, /* Offset=0x0000: Object Size, bytes */
|
||||
0x01211220, /* Offset=0x0004: Magic Number (TOC Part 2, ID) */
|
||||
0, /* Offset=0x0008: Key Storage Address */
|
||||
(int)&smifIpBlocksArr, /* Offset=0x000C: This points to a null terminated array of SMIF structures. */
|
||||
0x10000000u, /* Offset=0x0010: App image start address */
|
||||
/* Offset=0x0014-0x01F7: Reserved */
|
||||
[126] = 0x000002C2, /* Offset=0x01F8: Bits[ 1: 0] CLOCK_CONFIG (0=8MHz, 1=25MHz, 2=50MHz, 3=100MHz)
|
||||
Bits[ 4: 2] LISTEN_WINDOW (0=20ms, 1=10ms, 2=1ms, 3=0ms, 4=100ms)
|
||||
Bits[ 6: 5] SWJ_PINS_CTL (0/1/3=Disable SWJ, 2=Enable SWJ)
|
||||
Bits[ 8: 7] APP_AUTHENTICATION (0/2/3=Enable, 1=Disable)
|
||||
Bits[10: 9] FB_BOOTLOADER_CTL: UNUSED */
|
||||
[127] = 0x3BB30000 /* Offset=0x01FC: CRC16-CCITT (the upper 2 bytes contain the CRC and the lower 2 bytes are 0) */
|
||||
};
|
||||
|
||||
/** \} group_serial_flash_variables */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \} group_serial_flash */
|
|
@ -22,6 +22,11 @@
|
|||
#include "cy_retarget_io_pdl.h"
|
||||
#include "cy_result.h"
|
||||
|
||||
#include "cycfg_clocks.h"
|
||||
#include "cycfg_peripherals.h"
|
||||
#include "cycfg_pins.h"
|
||||
|
||||
#include "flash_qspi.h"
|
||||
#include "sysflash/sysflash.h"
|
||||
#include "flash_map_backend/flash_map_backend.h"
|
||||
|
||||
|
@ -56,6 +61,7 @@ static void do_boot(struct boot_rsp *rsp)
|
|||
int main(void)
|
||||
{
|
||||
struct boot_rsp rsp ;
|
||||
cy_rslt_t rc = !CY_RSLT_SUCCESS;
|
||||
|
||||
init_cycfg_clocks();
|
||||
init_cycfg_peripherals();
|
||||
|
@ -68,11 +74,29 @@ int main(void)
|
|||
|
||||
BOOT_LOG_INF("MCUBoot Bootloader Started");
|
||||
|
||||
if (boot_go(&rsp) == 0) {
|
||||
BOOT_LOG_INF("User Application validated successfully");
|
||||
do_boot(&rsp);
|
||||
} else
|
||||
BOOT_LOG_INF("MCUBoot Bootloader found none of bootable images") ;
|
||||
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
int smif_id = 1; /* Assume SlaveSelect_0 is used for External Memory */
|
||||
/* Acceptable values are:
|
||||
* 0 - SMIF disabled (no external memory);
|
||||
* 1, 2, 3 or 4 - slave select line memory module is connected to.
|
||||
*/
|
||||
rc = qspi_init_sfdp(smif_id);
|
||||
if(rc == CY_SMIF_SUCCESS)
|
||||
{
|
||||
BOOT_LOG_INF("External Memory initialized w/ SFDP.");
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOT_LOG_ERR("External Memory initialization w/ SFDP FAILED: 0x%02x", (int)rc);
|
||||
}
|
||||
if(0 == rc)
|
||||
#endif
|
||||
{
|
||||
if (boot_go(&rsp) == 0) {
|
||||
BOOT_LOG_INF("User Application validated successfully");
|
||||
do_boot(&rsp);
|
||||
} else
|
||||
BOOT_LOG_INF("MCUBoot Bootloader found none of bootable images") ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
#define FLASH_AREA_IMAGE_2 5
|
||||
#define FLASH_AREA_IMAGE_3 6
|
||||
|
||||
/* Uncomment if external flash is being used */
|
||||
/* #define CY_BOOT_USE_EXTERNAL_FLASH */
|
||||
|
||||
/* use PDL-defined offset or one from SMFI config */
|
||||
#define CY_SMIF_BASE_MEM_OFFSET (0x18000000)
|
||||
|
||||
#define CY_FLASH_ALIGN (CY_FLASH_SIZEOF_ROW)
|
||||
#define CY_FLASH_DEVICE_BASE (CY_FLASH_BASE)
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ endif
|
|||
# NOTE: Absolute pathes for now for the sake of development
|
||||
ifeq ($(HOST_OS), win)
|
||||
ifeq ($(COMPILER), GCC_ARM)
|
||||
TOOLCHAIN_PATH ?= c:/Users/$(USERNAME)/ModusToolbox_1.0/tools/gcc-7.2.1-1.0
|
||||
TOOLCHAIN_PATH ?= c:/Users/$(USERNAME)/ModusToolbox/tools_2.1/gcc-7.2.1
|
||||
MY_TOOLCHAIN_PATH:=$(subst \,/,$(TOOLCHAIN_PATH))
|
||||
TOOLCHAIN_PATH := $(MY_TOOLCHAIN_PATH)
|
||||
GCC_PATH := $(TOOLCHAIN_PATH)
|
||||
|
|
|
@ -139,7 +139,7 @@ app:
|
|||
$(MAKE) post_build
|
||||
|
||||
build: $(OUT_APP)/$(APP_NAME).hex
|
||||
$(GCC_PATH)/bin/arm-none-eabi-objdump $(OUT_APP)/$(APP_NAME).hex -s > $(OUT_APP)/$(APP_NAME).lst
|
||||
$(GCC_PATH)/bin/arm-none-eabi-objdump $(OUT_APP)/$(APP_NAME).elf -S --disassemble > $(OUT_APP)/$(APP_NAME).lst
|
||||
$(GCC_PATH)/bin/arm-none-eabi-objdump -h $(OUT_APP)/$(APP_NAME).elf
|
||||
$(GCC_PATH)/bin/arm-none-eabi-size --format=SysV $(OUT_APP)/$(APP_NAME).elf
|
||||
|
||||
|
|
|
@ -36,12 +36,14 @@
|
|||
|
||||
#include "flash_map_backend/flash_map_backend.h"
|
||||
#include <sysflash/sysflash.h>
|
||||
#include "cy_flash_psoc6.h"
|
||||
|
||||
#include "bootutil/bootutil_log.h"
|
||||
|
||||
#include "cy_pdl.h"
|
||||
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
#include "cy_smif_psoc6.h"
|
||||
#endif
|
||||
/*
|
||||
* For now, we only support one flash device.
|
||||
*
|
||||
|
@ -86,6 +88,7 @@ static struct flash_area primary_1 =
|
|||
.fa_size = CY_BOOT_PRIMARY_1_SIZE
|
||||
};
|
||||
|
||||
#ifndef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
static struct flash_area secondary_1 =
|
||||
{
|
||||
.fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
|
||||
|
@ -95,7 +98,15 @@ static struct flash_area secondary_1 =
|
|||
CY_BOOT_PRIMARY_1_SIZE,
|
||||
.fa_size = CY_BOOT_SECONDARY_1_SIZE
|
||||
};
|
||||
|
||||
#else
|
||||
static struct flash_area secondary_1 =
|
||||
{
|
||||
.fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
|
||||
.fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
|
||||
.fa_off = CY_SMIF_BASE_MEM_OFFSET,
|
||||
.fa_size = CY_BOOT_SECONDARY_1_SIZE
|
||||
};
|
||||
#endif
|
||||
#if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
|
||||
static struct flash_area primary_2 =
|
||||
{
|
||||
|
@ -199,26 +210,30 @@ void flash_area_close(const struct flash_area *fa)
|
|||
(void)fa;/* Nothing to do there */
|
||||
}
|
||||
|
||||
/* Reads `len` bytes of flash memory at `off` to the buffer at `dst` */
|
||||
/*
|
||||
* Reads `len` bytes of flash memory at `off` to the buffer at `dst`
|
||||
*/
|
||||
int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t addr;
|
||||
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
|
||||
/* check if requested offset not less then flash area (fa) start */
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
/* convert to absolute address inside a device*/
|
||||
addr = fa->fa_off + off;
|
||||
|
||||
rc = psoc6_flash_read(addr, dst, len);
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
/* flash read by simple memory copying */
|
||||
memcpy((void *)dst, (const void*)addr, (size_t)len);
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement/split into psoc6_smif_read()
|
||||
rc = psoc6_smif_read(fa, addr, dst, len);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -230,29 +245,52 @@ int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
|
|||
if (rc != 0) {
|
||||
BOOT_LOG_ERR("Flash area read error, rc = %d", (int)rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Writes `len` bytes of flash memory at `off` from the buffer at `src` */
|
||||
/*
|
||||
* Writes `len` bytes of flash memory at `off` from the buffer at `src`
|
||||
*/
|
||||
int flash_area_write(const struct flash_area *fa, uint32_t off,
|
||||
const void *src, uint32_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t addr;
|
||||
cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
|
||||
size_t write_start_addr;
|
||||
size_t write_end_addr;
|
||||
const uint32_t * row_ptr = NULL;
|
||||
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
|
||||
/* convert to absolute address inside a device */
|
||||
write_start_addr = fa->fa_off + off;
|
||||
write_end_addr = fa->fa_off + off + len;
|
||||
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
uint32_t row_number = 0;
|
||||
uint32_t row_addr = 0;
|
||||
|
||||
addr = fa->fa_off + off;
|
||||
rc = psoc6_flash_write(addr, src, len);
|
||||
assert(!(len % CY_FLASH_SIZEOF_ROW));
|
||||
|
||||
row_number = (write_end_addr - write_start_addr) / CY_FLASH_SIZEOF_ROW;
|
||||
row_addr = write_start_addr;
|
||||
|
||||
row_ptr = (uint32_t *) src;
|
||||
|
||||
for (uint32_t i = 1; i <= row_number + 1; i++){
|
||||
|
||||
rc = Cy_Flash_WriteRow(row_addr, row_ptr);
|
||||
row_addr = write_start_addr + i * (uint32_t) CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
row_number--;
|
||||
row_ptr = row_ptr + CY_FLASH_SIZEOF_ROW / 4;
|
||||
}
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement/split into psoc6_smif_write()
|
||||
rc = psoc6_smif_write(fa, write_start_addr, src, len);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -261,27 +299,41 @@ int flash_area_write(const struct flash_area *fa, uint32_t off,
|
|||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return (int) rc;
|
||||
}
|
||||
|
||||
/* Erases `len` bytes of flash memory at `off` */
|
||||
/*< Erases `len` bytes of flash memory at `off` */
|
||||
int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t addr;
|
||||
cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
|
||||
size_t erase_start_addr;
|
||||
size_t erase_end_addr;
|
||||
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
assert(!(len % CY_FLASH_SIZEOF_ROW));
|
||||
|
||||
/* convert to absolute address inside a device*/
|
||||
erase_start_addr = fa->fa_off + off;
|
||||
erase_end_addr = fa->fa_off + off + len;
|
||||
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
assert(off < fa->fa_off);
|
||||
assert(off + len < fa->fa_off);
|
||||
int row_number = 0;
|
||||
uint32_t row_addr = 0;
|
||||
|
||||
addr = fa->fa_off + off;
|
||||
rc = psoc6_flash_erase(addr, len);
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
row_number = (erase_end_addr - erase_start_addr) / CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
while (row_number != 0)
|
||||
{
|
||||
row_number--;
|
||||
row_addr = erase_start_addr + row_number * (uint32_t) CY_FLASH_SIZEOF_ROW;
|
||||
rc = Cy_Flash_EraseRow(row_addr);
|
||||
}
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement/split into psoc6_smif_erase()
|
||||
rc = psoc6_smif_erase(erase_start_addr, len);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -289,21 +341,21 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
|
|||
/* incorrect/non-existing flash device id */
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
return (int) rc;
|
||||
}
|
||||
|
||||
/* Returns this `flash_area`s alignment */
|
||||
/*< Returns this `flash_area`s alignment */
|
||||
size_t flash_area_align(const struct flash_area *fa)
|
||||
{
|
||||
uint8_t ret = -1;
|
||||
int ret = -1;
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
ret = CY_FLASH_ALIGN;
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement for SMIF WR/ERASE size
|
||||
return qspi_get_prog_size();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -315,22 +367,23 @@ size_t flash_area_align(const struct flash_area *fa)
|
|||
}
|
||||
|
||||
#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
|
||||
/* Initializes an array of flash_area elements for the slot's sectors */
|
||||
/*< Initializes an array of flash_area elements for the slot's sectors */
|
||||
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
// TODO:
|
||||
(void)idx;
|
||||
(void)cnt;
|
||||
rc = 0;
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement/split into psoc6_smif_erase()
|
||||
(void)idx;
|
||||
(void)cnt;
|
||||
rc = 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -338,7 +391,6 @@ int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa)
|
|||
/* incorrect/non-existing flash device id */
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
@ -387,12 +439,12 @@ uint8_t flash_area_erased_val(const struct flash_area *fap)
|
|||
|
||||
if (fap->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE ;
|
||||
ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if ((fap->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
ret = CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE ;
|
||||
ret = CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -406,7 +458,6 @@ uint8_t flash_area_erased_val(const struct flash_area *fap)
|
|||
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
|
||||
void *dst, uint32_t len)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t *mem_dest;
|
||||
int rc;
|
||||
|
||||
|
@ -416,7 +467,7 @@ int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
|
|||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
if (mem_dest[i] != flash_area_erased_val(fa)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -424,14 +475,12 @@ int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
|
||||
int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
|
||||
{
|
||||
int rc = 0;
|
||||
uint32_t i = 0;
|
||||
struct flash_area *fa;
|
||||
size_t sector_size = 0;
|
||||
size_t sectors_n = 0;
|
||||
uint32_t addr = 0;
|
||||
struct flash_area *fa = NULL;
|
||||
|
||||
while(NULL != boot_area_descs[i])
|
||||
{
|
||||
|
@ -443,17 +492,20 @@ int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
|
|||
i++;
|
||||
}
|
||||
|
||||
|
||||
if(NULL != boot_area_descs[i])
|
||||
{
|
||||
size_t sector_size = 0;
|
||||
|
||||
if(fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
|
||||
{
|
||||
sector_size = CY_FLASH_SIZEOF_ROW;
|
||||
}
|
||||
#ifdef CY_USE_EXTERNAL_FLASH
|
||||
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
|
||||
else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
|
||||
{
|
||||
// TODO: implement for SMIF
|
||||
/* implement for SMIF */
|
||||
/* lets assume they are equal */
|
||||
sector_size = CY_FLASH_SIZEOF_ROW;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -463,6 +515,9 @@ int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
|
|||
|
||||
if(0 == rc)
|
||||
{
|
||||
uint32_t addr = 0;
|
||||
size_t sectors_n = 0;
|
||||
|
||||
sectors_n = (fa->fa_size + (sector_size - 1)) / sector_size;
|
||||
assert(sectors_n <= *cnt);
|
||||
|
||||
|
@ -484,3 +539,4 @@ int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret)
|
|||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Cypress Semiconductors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#ifdef MCUBOOT_HAVE_ASSERT_H
|
||||
#include "mcuboot_config/mcuboot_assert.h"
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "cy_device_headers.h"
|
||||
#include "cy_flash_psoc6.h"
|
||||
|
||||
#include "cy_flash.h"
|
||||
#include "cy_syspm.h"
|
||||
|
||||
#define PSOC6_WR_SUCCESS 0
|
||||
#define PSOC6_WR_ERROR_INVALID_PARAMETER 1
|
||||
#define PSOC6_WR_ERROR_FLASH_WRITE 2
|
||||
|
||||
#define PSOC6_FLASH_ERASE_BLOCK_SIZE CY_FLASH_SIZEOF_ROW /* PSoC6 Flash erases by Row */
|
||||
|
||||
int psoc6_flash_read(off_t addr, void *data, size_t len)
|
||||
{
|
||||
/* flash read by simple memory copying */
|
||||
memcpy((void *)data, (const void*)addr, (size_t)len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int psoc6_flash_write(off_t addr,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = psoc6_flash_write_hal((uint8_t *)data, addr, len);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int psoc6_flash_erase(off_t addr, size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
uint32_t addrStart, addrEnd, address;
|
||||
uint32_t remStart, remEnd;
|
||||
uint32_t rowIdxStart, rowIdxEnd, rowNum;
|
||||
uint8_t buff[CY_FLASH_SIZEOF_ROW];
|
||||
|
||||
addrStart = addr;
|
||||
addrEnd = addrStart + size;
|
||||
|
||||
/* find if area bounds are aligned to rows */
|
||||
remStart = addrStart%CY_FLASH_SIZEOF_ROW;
|
||||
remEnd = addrEnd%CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
/* find which row numbers are affected for full Erase */
|
||||
rowIdxStart = addrStart/CY_FLASH_SIZEOF_ROW;
|
||||
rowIdxEnd = addrEnd/CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
if(remStart != 0)
|
||||
{/* first row is fragmented, move to next */
|
||||
rowIdxStart++;
|
||||
}
|
||||
|
||||
/* total number of rows for full erase */
|
||||
rowNum = rowIdxEnd - rowIdxStart;
|
||||
address = rowIdxStart*CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
while(rowNum>0)
|
||||
{
|
||||
rc = Cy_Flash_EraseRow(address);
|
||||
assert(rc == 0);
|
||||
address += CY_FLASH_SIZEOF_ROW;
|
||||
rowNum--;
|
||||
}
|
||||
|
||||
/* if Start of erase area is unaligned */
|
||||
if(remStart != 0)
|
||||
{
|
||||
/* first row is fragmented, shift left by one*/
|
||||
rowIdxStart--;
|
||||
|
||||
/* find start address of fragmented row */
|
||||
address = rowIdxStart*CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
/* store fragmented row contents first */
|
||||
memcpy((void *)buff, (const void*)address, remStart);
|
||||
|
||||
/* erase fragmented row */
|
||||
rc = Cy_Flash_EraseRow(address);
|
||||
assert(rc == 0);
|
||||
|
||||
/* write stored back */
|
||||
rc = psoc6_flash_write_hal(buff, address, remStart);
|
||||
assert(rc == 0);
|
||||
}
|
||||
/* if End of erase area is unaligned */
|
||||
if(remEnd != 0)
|
||||
{
|
||||
/* find start address of fragmented row */
|
||||
address = rowIdxEnd*CY_FLASH_SIZEOF_ROW;
|
||||
|
||||
/* store fragmented row contents first */
|
||||
memcpy((void *)buff, (const void*)addrEnd, CY_FLASH_SIZEOF_ROW-remEnd);
|
||||
|
||||
/* erase fragmented row */
|
||||
rc = Cy_Flash_EraseRow(address);
|
||||
assert(rc == 0);
|
||||
|
||||
/* write stored back */
|
||||
rc = psoc6_flash_write_hal(buff, addrEnd, CY_FLASH_SIZEOF_ROW-remEnd);
|
||||
assert(rc == 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name: psoc6_flash_write_hal
|
||||
****************************************************************************//**
|
||||
*
|
||||
* This function writes the data to the PSOC6's Flash. It will check the
|
||||
* appropriate alignment of a start address and also perform an address range
|
||||
* check based on the length before performing the write operation.
|
||||
* This function performs memory compare and writes only row where there are new
|
||||
* data to write.
|
||||
*
|
||||
* \param addr: Pointer to the buffer containing the data to be stored.
|
||||
* \param data: Pointer to the array or variable in the flash.
|
||||
* \param len: The length of the data in bytes.
|
||||
*
|
||||
* \return
|
||||
* PSOC6_WR_SUCCESS A successful write
|
||||
* PSOC6_WR_ERROR_INVALID_PARAMETER At least one of the input parameters is invalid
|
||||
* PSOC6_WR__ERROR_FLASH_WRITE Error in flash Write
|
||||
*
|
||||
*******************************************************************************/
|
||||
int psoc6_flash_write_hal(uint8_t data[],
|
||||
uint32_t address,
|
||||
uint32_t len)
|
||||
{
|
||||
int retCode;
|
||||
cy_en_flashdrv_status_t rc = CY_FLASH_DRV_SUCCESS;
|
||||
|
||||
uint32_t writeBuffer[CY_FLASH_SIZEOF_ROW / sizeof(uint32_t)];
|
||||
uint32_t rowId;
|
||||
uint32_t dstIndex;
|
||||
uint32_t srcIndex = 0u;
|
||||
uint32_t eeOffset;
|
||||
uint32_t byteOffset;
|
||||
uint32_t rowsNotEqual;
|
||||
uint8_t *writeBufferPointer;
|
||||
|
||||
eeOffset = (uint32_t)address;
|
||||
writeBufferPointer = (uint8_t*)writeBuffer;
|
||||
|
||||
bool cond1;
|
||||
|
||||
/* Make sure, that varFlash[] points to Flash */
|
||||
cond1 = ((eeOffset >= CY_FLASH_BASE) &&
|
||||
((eeOffset + len) <= (CY_FLASH_BASE + CY_FLASH_SIZE)));
|
||||
|
||||
if(cond1)
|
||||
{
|
||||
eeOffset -= CY_FLASH_BASE;
|
||||
rowId = eeOffset / CY_FLASH_SIZEOF_ROW;
|
||||
byteOffset = CY_FLASH_SIZEOF_ROW * rowId;
|
||||
|
||||
while((srcIndex < len) && (rc == CY_FLASH_DRV_SUCCESS))
|
||||
{
|
||||
rowsNotEqual = 0u;
|
||||
/* Copy data to the write buffer either from the source buffer or from the flash */
|
||||
for(dstIndex = 0u; dstIndex < CY_FLASH_SIZEOF_ROW; dstIndex++)
|
||||
{
|
||||
if((byteOffset >= eeOffset) && (srcIndex < len))
|
||||
{
|
||||
writeBufferPointer[dstIndex] = data[srcIndex];
|
||||
/* Detect that row programming is required */
|
||||
if((rowsNotEqual == 0u) && (CY_GET_REG8(CY_FLASH_BASE + byteOffset) != data[srcIndex]))
|
||||
{
|
||||
rowsNotEqual = 1u;
|
||||
}
|
||||
srcIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeBufferPointer[dstIndex] = CY_GET_REG8(CY_FLASH_BASE + byteOffset);
|
||||
}
|
||||
byteOffset++;
|
||||
}
|
||||
|
||||
if(rowsNotEqual != 0u)
|
||||
{
|
||||
/* Write flash row */
|
||||
rc = Cy_Flash_WriteRow((rowId * CY_FLASH_SIZEOF_ROW) + CY_FLASH_BASE, writeBuffer);
|
||||
}
|
||||
|
||||
/* Go to the next row */
|
||||
rowId++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Return error code */
|
||||
switch(rc)
|
||||
{
|
||||
case CY_FLASH_DRV_SUCCESS:
|
||||
retCode = PSOC6_WR_SUCCESS;
|
||||
break;
|
||||
|
||||
case CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
|
||||
case CY_FLASH_DRV_INVALID_FLASH_ADDR:
|
||||
retCode = PSOC6_WR_ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
|
||||
default:
|
||||
retCode = PSOC6_WR_ERROR_FLASH_WRITE;
|
||||
break;
|
||||
}
|
||||
return(retCode);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/***************************************************************************//**
|
||||
* \file cy_smif_psoc6.c
|
||||
* \version 1.0
|
||||
*
|
||||
* \brief
|
||||
* This is the source file of external flash driver adoption layer between PSoC6
|
||||
* and standard MCUBoot code.
|
||||
*
|
||||
********************************************************************************
|
||||
* \copyright
|
||||
*
|
||||
* (c) 2020, Cypress Semiconductor Corporation
|
||||
* or a subsidiary of Cypress Semiconductor Corporation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* This software, including source code, documentation and related
|
||||
* materials ("Software"), is owned by Cypress Semiconductor
|
||||
* Corporation or one of its subsidiaries ("Cypress") and is protected by
|
||||
* and subject to worldwide patent protection (United States and foreign),
|
||||
* United States copyright laws and international treaty provisions.
|
||||
* Therefore, you may use this Software only as provided in the license
|
||||
* agreement accompanying the software package from which you
|
||||
* obtained this Software ("EULA").
|
||||
*
|
||||
* If no EULA applies, Cypress hereby grants you a personal, non-
|
||||
* exclusive, non-transferable license to copy, modify, and compile the
|
||||
* Software source code solely for use in connection with Cypress?s
|
||||
* integrated circuit products. Any reproduction, modification, translation,
|
||||
* compilation, or representation of this Software except as specified
|
||||
* above is prohibited without the express written permission of Cypress.
|
||||
*
|
||||
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
|
||||
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
|
||||
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. Cypress reserves the right to make
|
||||
* changes to the Software without notice. Cypress does not assume any
|
||||
* liability arising out of the application or use of the Software or any
|
||||
* product or circuit described in the Software. Cypress does not
|
||||
* authorize its products for use in any products where a malfunction or
|
||||
* failure of the Cypress product may reasonably be expected to result in
|
||||
* significant property damage, injury or death ("High Risk Product"). By
|
||||
* including Cypress's product in a High Risk Product, the manufacturer
|
||||
* of such system or application assumes all risk of such use and in doing
|
||||
* so agrees to indemnify Cypress against all liability.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#ifdef MCUBOOT_HAVE_ASSERT_H
|
||||
#include "mcuboot_config/mcuboot_assert.h"
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "flash_map_backend/flash_map_backend.h"
|
||||
#include <sysflash/sysflash.h>
|
||||
|
||||
#include "cy_device_headers.h"
|
||||
#include "cy_smif_psoc6.h"
|
||||
#include "cy_flash.h"
|
||||
#include "cy_syspm.h"
|
||||
|
||||
#include "flash_qspi.h"
|
||||
|
||||
#define PSOC6_WR_SUCCESS (0)
|
||||
#define PSOC6_WR_ERROR_INVALID_PARAMETER (1)
|
||||
#define PSOC6_WR_ERROR_FLASH_WRITE (2)
|
||||
|
||||
#define PSOC6_FLASH_ERASE_BLOCK_SIZE CY_FLASH_SIZEOF_ROW /* PSoC6 Flash erases by Row */
|
||||
|
||||
int psoc6_smif_read(const struct flash_area *fap,
|
||||
off_t addr,
|
||||
void *data,
|
||||
size_t len)
|
||||
{
|
||||
int rc = -1;
|
||||
cy_stc_smif_mem_config_t *cfg;
|
||||
cy_en_smif_status_t st;
|
||||
uint32_t address;
|
||||
|
||||
cfg = qspi_get_memory_config(FLASH_DEVICE_GET_EXT_INDEX(fap->fa_device_id));
|
||||
|
||||
address = addr - CY_SMIF_BASE_MEM_OFFSET;
|
||||
|
||||
st = Cy_SMIF_MemRead(qspi_get_device(), cfg, address, data, len, qspi_get_context());
|
||||
if (st == CY_SMIF_SUCCESS) {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int psoc6_smif_write(const struct flash_area *fap,
|
||||
off_t addr,
|
||||
const void *data,
|
||||
size_t len)
|
||||
{
|
||||
int rc = -1;
|
||||
cy_en_smif_status_t st;
|
||||
cy_stc_smif_mem_config_t *cfg;
|
||||
uint32_t address;
|
||||
|
||||
cfg = qspi_get_memory_config(FLASH_DEVICE_GET_EXT_INDEX(fap->fa_device_id));
|
||||
|
||||
address = addr - CY_SMIF_BASE_MEM_OFFSET;
|
||||
|
||||
st = Cy_SMIF_MemWrite(qspi_get_device(), cfg, address, data, len, qspi_get_context());
|
||||
if (st == CY_SMIF_SUCCESS) {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int psoc6_smif_erase(off_t addr, size_t size)
|
||||
{
|
||||
int rc = -1;
|
||||
cy_en_smif_status_t st;
|
||||
uint32_t address;
|
||||
|
||||
/* It is erase sector-only
|
||||
*
|
||||
* There is no power-safe way to erase flash partially
|
||||
* this leads upgrade slots have to be at least
|
||||
* eraseSectorSize far from each other;
|
||||
*/
|
||||
cy_stc_smif_mem_config_t *memCfg = qspi_get_memory_config(0);
|
||||
|
||||
address = (addr - CY_SMIF_BASE_MEM_OFFSET ) & ~((uint32_t)(memCfg->deviceCfg->eraseSize - 1u));
|
||||
|
||||
(void)size;
|
||||
|
||||
st = Cy_SMIF_MemEraseSector(qspi_get_device(),
|
||||
memCfg,
|
||||
address,
|
||||
memCfg->deviceCfg->eraseSize,
|
||||
qspi_get_context());
|
||||
if (st == CY_SMIF_SUCCESS) {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,475 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
/***************************************************************************//**
|
||||
* \file flash_qspi.c
|
||||
* \version 1.0
|
||||
*
|
||||
* \brief
|
||||
* This is the source file of external flash driver adaptation layer between PSoC6
|
||||
* and standard MCUBoot code.
|
||||
*
|
||||
********************************************************************************
|
||||
* \copyright
|
||||
*
|
||||
* (c) 2020, Cypress Semiconductor Corporation
|
||||
* or a subsidiary of Cypress Semiconductor Corporation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* This software, including source code, documentation and related
|
||||
* materials ("Software"), is owned by Cypress Semiconductor
|
||||
* Corporation or one of its subsidiaries ("Cypress") and is protected by
|
||||
* and subject to worldwide patent protection (United States and foreign),
|
||||
* United States copyright laws and international treaty provisions.
|
||||
* Therefore, you may use this Software only as provided in the license
|
||||
* agreement accompanying the software package from which you
|
||||
* obtained this Software ("EULA").
|
||||
*
|
||||
* If no EULA applies, Cypress hereby grants you a personal, non-
|
||||
* exclusive, non-transferable license to copy, modify, and compile the
|
||||
* Software source code solely for use in connection with Cypress?s
|
||||
* integrated circuit products. Any reproduction, modification, translation,
|
||||
* compilation, or representation of this Software except as specified
|
||||
* above is prohibited without the express written permission of Cypress.
|
||||
*
|
||||
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
|
||||
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
|
||||
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. Cypress reserves the right to make
|
||||
* changes to the Software without notice. Cypress does not assume any
|
||||
* liability arising out of the application or use of the Software or any
|
||||
* product or circuit described in the Software. Cypress does not
|
||||
* authorize its products for use in any products where a malfunction or
|
||||
* failure of the Cypress product may reasonably be expected to result in
|
||||
* significant property damage, injury or death ("High Risk Product"). By
|
||||
* including Cypress's product in a High Risk Product, the manufacturer
|
||||
* of such system or application assumes all risk of such use and in doing
|
||||
* so agrees to indemnify Cypress against all liability.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "cy_pdl.h"
|
||||
#include <stdio.h>
|
||||
#include "flash_qspi.h"
|
||||
|
||||
#define CY_SMIF_SYSCLK_HFCLK_DIVIDER CY_SYSCLK_CLKHF_DIVIDE_BY_4
|
||||
|
||||
/* This is the board specific stuff that should align with your board.
|
||||
*
|
||||
* QSPI resources:
|
||||
*
|
||||
* SS0 - P11_2
|
||||
* SS1 - P11_1
|
||||
* SS2 - P11_0
|
||||
* SS3 - P12_4
|
||||
*
|
||||
* D3 - P11_3
|
||||
* D2 - P11_4
|
||||
* D1 - P11_5
|
||||
* D0 - P11_6
|
||||
*
|
||||
* SCK - P11_7
|
||||
*
|
||||
* SMIF Block - SMIF0
|
||||
*
|
||||
*/
|
||||
|
||||
/* SMIF SlaveSelect Configurations */
|
||||
struct qspi_ss_config
|
||||
{
|
||||
GPIO_PRT_Type* SS_Port;
|
||||
int SS_Pin;
|
||||
en_hsiom_sel_t SS_Mux;
|
||||
};
|
||||
|
||||
#if (defined(PSOC_064_2M) || \
|
||||
defined(PSOC_064_1M) || \
|
||||
defined(PSOC_062_2M))
|
||||
#define CY_BOOTLOADER_SMIF_SS_CFG_NUM 4
|
||||
#elif defined(PSOC_064_512K)
|
||||
#define CY_BOOTLOADER_SMIF_SS_CFG_NUM 3
|
||||
#else
|
||||
#error "Platform device name is unsupported."
|
||||
#endif
|
||||
struct qspi_ss_config qspi_SS_Configuration[CY_BOOTLOADER_SMIF_SS_CFG_NUM] =
|
||||
{
|
||||
{
|
||||
.SS_Port = GPIO_PRT11,
|
||||
.SS_Pin = 2,
|
||||
.SS_Mux = P11_2_SMIF_SPI_SELECT0
|
||||
},
|
||||
{
|
||||
.SS_Port = GPIO_PRT11,
|
||||
.SS_Pin = 1,
|
||||
.SS_Mux = P11_1_SMIF_SPI_SELECT1
|
||||
},
|
||||
{
|
||||
.SS_Port = GPIO_PRT11,
|
||||
.SS_Pin = 0,
|
||||
.SS_Mux = P11_0_SMIF_SPI_SELECT2
|
||||
},
|
||||
#if(CY_BOOTLOADER_SMIF_SS_CFG_NUM > 3)
|
||||
{
|
||||
.SS_Port = GPIO_PRT12,
|
||||
.SS_Pin = 4,
|
||||
.SS_Mux = P12_4_SMIF_SPI_SELECT3
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
static GPIO_PRT_Type *D3Port = GPIO_PRT11;
|
||||
static int D3Pin = 3;
|
||||
static en_hsiom_sel_t D3MuxPort = P11_3_SMIF_SPI_DATA3;
|
||||
|
||||
static GPIO_PRT_Type *D2Port = GPIO_PRT11;
|
||||
static int D2Pin = 4;
|
||||
static en_hsiom_sel_t D2MuxPort = P11_4_SMIF_SPI_DATA2;
|
||||
|
||||
static GPIO_PRT_Type *D1Port = GPIO_PRT11;
|
||||
static int D1Pin = 5;
|
||||
static en_hsiom_sel_t D1MuxPort = P11_5_SMIF_SPI_DATA1;
|
||||
|
||||
static GPIO_PRT_Type *D0Port = GPIO_PRT11;
|
||||
static int D0Pin = 6;
|
||||
static en_hsiom_sel_t D0MuxPort = P11_6_SMIF_SPI_DATA0;
|
||||
|
||||
static GPIO_PRT_Type *SCKPort = GPIO_PRT11;
|
||||
static int SCKPin = 7;
|
||||
static en_hsiom_sel_t SCKMuxPort = P11_7_SMIF_SPI_CLK;
|
||||
|
||||
static SMIF_Type *QSPIPort = SMIF0;
|
||||
|
||||
cy_stc_smif_mem_cmd_t sfdpcmd =
|
||||
{
|
||||
.command = 0x5A,
|
||||
.cmdWidth = CY_SMIF_WIDTH_SINGLE,
|
||||
.addrWidth = CY_SMIF_WIDTH_SINGLE,
|
||||
.mode = 0xFFFFFFFFU,
|
||||
.dummyCycles = 8,
|
||||
.dataWidth = CY_SMIF_WIDTH_SINGLE,
|
||||
};
|
||||
|
||||
static cy_stc_smif_mem_cmd_t rdcmd0;
|
||||
static cy_stc_smif_mem_cmd_t wrencmd0;
|
||||
static cy_stc_smif_mem_cmd_t wrdiscmd0;
|
||||
static cy_stc_smif_mem_cmd_t erasecmd0;
|
||||
static cy_stc_smif_mem_cmd_t chiperasecmd0;
|
||||
static cy_stc_smif_mem_cmd_t pgmcmd0;
|
||||
static cy_stc_smif_mem_cmd_t readsts0;
|
||||
static cy_stc_smif_mem_cmd_t readstsqecmd0;
|
||||
static cy_stc_smif_mem_cmd_t writestseqcmd0;
|
||||
|
||||
static cy_stc_smif_mem_device_cfg_t dev_sfdp_0 =
|
||||
{
|
||||
.numOfAddrBytes = 4,
|
||||
.readSfdpCmd = &sfdpcmd,
|
||||
.readCmd = &rdcmd0,
|
||||
.writeEnCmd = &wrencmd0,
|
||||
.writeDisCmd = &wrdiscmd0,
|
||||
.programCmd = &pgmcmd0,
|
||||
.eraseCmd = &erasecmd0,
|
||||
.chipEraseCmd = &chiperasecmd0,
|
||||
.readStsRegWipCmd = &readsts0,
|
||||
.readStsRegQeCmd = &readstsqecmd0,
|
||||
.writeStsRegQeCmd = &writestseqcmd0,
|
||||
};
|
||||
|
||||
static cy_stc_smif_mem_config_t mem_sfdp_0 =
|
||||
{
|
||||
/* The base address the memory slave is mapped to in the PSoC memory map.
|
||||
Valid when the memory-mapped mode is enabled. */
|
||||
.baseAddress = 0x18000000U,
|
||||
/* The size allocated in the PSoC memory map, for the memory slave device.
|
||||
The size is allocated from the base address. Valid when the memory mapped mode is enabled. */
|
||||
/* .memMappedSize = 0x4000000U, */
|
||||
.flags = CY_SMIF_FLAG_DETECT_SFDP,
|
||||
.slaveSelect = CY_SMIF_SLAVE_SELECT_0,
|
||||
.dataSelect = CY_SMIF_DATA_SEL0,
|
||||
.deviceCfg = &dev_sfdp_0
|
||||
};
|
||||
|
||||
cy_stc_smif_mem_config_t *mems_sfdp[1] =
|
||||
{
|
||||
&mem_sfdp_0
|
||||
};
|
||||
|
||||
/* make it exported if used in TOC (cy_serial_flash_prog.c) */
|
||||
/* cy_stc_smif_block_config_t smifBlockConfig_sfdp = */
|
||||
static cy_stc_smif_block_config_t smifBlockConfig_sfdp =
|
||||
{
|
||||
.memCount = 1,
|
||||
.memConfig = mems_sfdp,
|
||||
};
|
||||
|
||||
static cy_stc_smif_block_config_t *smif_blk_config;
|
||||
|
||||
static cy_stc_smif_context_t QSPI_context;
|
||||
|
||||
cy_stc_smif_config_t const QSPI_config =
|
||||
{
|
||||
.mode = CY_SMIF_NORMAL,
|
||||
.deselectDelay = 1,
|
||||
.rxClockSel = CY_SMIF_SEL_INV_INTERNAL_CLK,
|
||||
.blockEvent = CY_SMIF_BUS_ERROR
|
||||
};
|
||||
|
||||
cy_stc_sysint_t smifIntConfig =
|
||||
{/* ATTENTION: make sure proper Interrupts configured for CM0p or M4 cores */
|
||||
.intrSrc = NvicMux7_IRQn,
|
||||
.cm0pSrc = smif_interrupt_IRQn,
|
||||
.intrPriority = 1
|
||||
};
|
||||
|
||||
/* SMIF pinouts configurations */
|
||||
static cy_stc_gpio_pin_config_t QSPI_SS_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG_IN_OFF,
|
||||
.hsiom = P11_2_SMIF_SPI_SELECT0, /* lets use SS0 by default */
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
const cy_stc_gpio_pin_config_t QSPI_DATA3_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG,
|
||||
.hsiom = P11_3_SMIF_SPI_DATA3,
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
const cy_stc_gpio_pin_config_t QSPI_DATA2_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG,
|
||||
.hsiom = P11_4_SMIF_SPI_DATA2,
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
const cy_stc_gpio_pin_config_t QSPI_DATA1_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG,
|
||||
.hsiom = P11_5_SMIF_SPI_DATA1,
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
const cy_stc_gpio_pin_config_t QSPI_DATA0_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG,
|
||||
.hsiom = P11_6_SMIF_SPI_DATA0,
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
const cy_stc_gpio_pin_config_t QSPI_SCK_config =
|
||||
{
|
||||
.outVal = 1,
|
||||
.driveMode = CY_GPIO_DM_STRONG_IN_OFF,
|
||||
.hsiom = P11_7_SMIF_SPI_CLK,
|
||||
.intEdge = CY_GPIO_INTR_DISABLE,
|
||||
.intMask = 0UL,
|
||||
.vtrip = CY_GPIO_VTRIP_CMOS,
|
||||
.slewRate = CY_GPIO_SLEW_FAST,
|
||||
.driveSel = CY_GPIO_DRIVE_1_2,
|
||||
.vregEn = 0UL,
|
||||
.ibufMode = 0UL,
|
||||
.vtripSel = 0UL,
|
||||
.vrefSel = 0UL,
|
||||
.vohSel = 0UL,
|
||||
};
|
||||
|
||||
void Isr_SMIF(void)
|
||||
{
|
||||
Cy_SMIF_Interrupt(QSPIPort, &QSPI_context);
|
||||
}
|
||||
|
||||
cy_en_smif_status_t qspi_init_hardware()
|
||||
{
|
||||
cy_en_smif_status_t st;
|
||||
|
||||
|
||||
Cy_GPIO_Pin_Init(D3Port, D3Pin, &QSPI_DATA3_config);
|
||||
Cy_GPIO_SetHSIOM(D3Port, D3Pin, D3MuxPort);
|
||||
|
||||
Cy_GPIO_Pin_Init(D2Port, D2Pin, &QSPI_DATA2_config);
|
||||
Cy_GPIO_SetHSIOM(D2Port, D2Pin, D2MuxPort);
|
||||
|
||||
Cy_GPIO_Pin_Init(D1Port, D1Pin, &QSPI_DATA1_config);
|
||||
Cy_GPIO_SetHSIOM(D1Port, D1Pin, D1MuxPort);
|
||||
|
||||
Cy_GPIO_Pin_Init(D0Port, D0Pin, &QSPI_DATA0_config);
|
||||
Cy_GPIO_SetHSIOM(D0Port, D0Pin, D0MuxPort);
|
||||
|
||||
Cy_GPIO_Pin_Init(SCKPort, SCKPin, &QSPI_SCK_config);
|
||||
Cy_GPIO_SetHSIOM(SCKPort, SCKPin, SCKMuxPort);
|
||||
|
||||
Cy_SysClk_ClkHfSetSource(CY_SYSCLK_CLKHF_IN_CLKPATH2, CY_SYSCLK_CLKHF_IN_CLKPATH0);
|
||||
Cy_SysClk_ClkHfSetDivider(CY_SYSCLK_CLKHF_IN_CLKPATH2, CY_SMIF_SYSCLK_HFCLK_DIVIDER);
|
||||
Cy_SysClk_ClkHfEnable(CY_SYSCLK_CLKHF_IN_CLKPATH2);
|
||||
|
||||
/*
|
||||
* Setup the interrupt for the SMIF block. For the CM0 there
|
||||
* is a two stage process to setup the interrupts.
|
||||
*/
|
||||
Cy_SysInt_Init(&smifIntConfig, Isr_SMIF);
|
||||
|
||||
st = Cy_SMIF_Init(QSPIPort, &QSPI_config, 1000, &QSPI_context);
|
||||
if (st != CY_SMIF_SUCCESS)
|
||||
{
|
||||
return st;
|
||||
}
|
||||
NVIC_EnableIRQ(smifIntConfig.intrSrc); /* Finally, Enable the SMIF interrupt */
|
||||
|
||||
Cy_SMIF_Enable(QSPIPort, &QSPI_context);
|
||||
|
||||
return CY_SMIF_SUCCESS;
|
||||
}
|
||||
|
||||
cy_stc_smif_mem_config_t *qspi_get_memory_config(int index)
|
||||
{
|
||||
return smif_blk_config->memConfig[index];
|
||||
}
|
||||
|
||||
SMIF_Type *qspi_get_device()
|
||||
{
|
||||
return QSPIPort;
|
||||
}
|
||||
|
||||
cy_stc_smif_context_t *qspi_get_context()
|
||||
{
|
||||
return &QSPI_context;
|
||||
}
|
||||
|
||||
cy_en_smif_status_t qspi_init(cy_stc_smif_block_config_t *blk_config)
|
||||
{
|
||||
cy_en_smif_status_t st;
|
||||
|
||||
st = qspi_init_hardware();
|
||||
if (st == CY_SMIF_SUCCESS)
|
||||
{
|
||||
smif_blk_config = blk_config;
|
||||
st = Cy_SMIF_MemInit(QSPIPort, smif_blk_config, &QSPI_context);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
cy_en_smif_status_t qspi_init_sfdp(uint32_t smif_id)
|
||||
{
|
||||
cy_en_smif_status_t stat = CY_SMIF_SUCCESS;
|
||||
|
||||
cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
|
||||
|
||||
GPIO_PRT_Type *SS_Port;
|
||||
int SS_Pin;
|
||||
en_hsiom_sel_t SS_MuxPort;
|
||||
|
||||
switch(smif_id)
|
||||
{
|
||||
case 1:
|
||||
(*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_0;
|
||||
break;
|
||||
case 2:
|
||||
(*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_1;
|
||||
break;
|
||||
case 3:
|
||||
(*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_2;
|
||||
break;
|
||||
#if(CY_BOOTLOADER_SMIF_SS_CFG_NUM > 3)
|
||||
case 4:
|
||||
(*memCfg)->slaveSelect = CY_SMIF_SLAVE_SELECT_3;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
stat = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(CY_SMIF_SUCCESS == stat)
|
||||
{
|
||||
SS_Port = qspi_SS_Configuration[smif_id-1].SS_Port;
|
||||
SS_Pin = qspi_SS_Configuration[smif_id-1].SS_Pin;
|
||||
SS_MuxPort = qspi_SS_Configuration[smif_id-1].SS_Mux;
|
||||
|
||||
QSPI_SS_config.hsiom = SS_MuxPort;
|
||||
|
||||
Cy_GPIO_Pin_Init(SS_Port, SS_Pin, &QSPI_SS_config);
|
||||
Cy_GPIO_SetHSIOM(SS_Port, SS_Pin, SS_MuxPort);
|
||||
|
||||
stat = qspi_init(&smifBlockConfig_sfdp);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
uint32_t qspi_get_prog_size(void)
|
||||
{
|
||||
cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
|
||||
return (*memCfg)->deviceCfg->programSize;
|
||||
}
|
||||
|
||||
uint32_t qspi_get_erase_size(void)
|
||||
{
|
||||
cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
|
||||
return (*memCfg)->deviceCfg->eraseSize;
|
||||
}
|
||||
|
||||
uint32_t qspi_get_mem_size(void)
|
||||
{
|
||||
cy_stc_smif_mem_config_t **memCfg = smifBlockConfig_sfdp.memConfig;
|
||||
return (*memCfg)->deviceCfg->memSize;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/***************************************************************************//**
|
||||
* \file flash_qspi.h
|
||||
* \version 1.0
|
||||
*
|
||||
* \brief
|
||||
* This is the header file for PSoC6 external flash driver adoption layer.
|
||||
*
|
||||
********************************************************************************
|
||||
* \copyright
|
||||
*
|
||||
* © 2020, Cypress Semiconductor Corporation
|
||||
* or a subsidiary of Cypress Semiconductor Corporation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* This software, including source code, documentation and related
|
||||
* materials ("Software"), is owned by Cypress Semiconductor
|
||||
* Corporation or one of its subsidiaries ("Cypress") and is protected by
|
||||
* and subject to worldwide patent protection (United States and foreign),
|
||||
* United States copyright laws and international treaty provisions.
|
||||
* Therefore, you may use this Software only as provided in the license
|
||||
* agreement accompanying the software package from which you
|
||||
* obtained this Software ("EULA").
|
||||
*
|
||||
* If no EULA applies, Cypress hereby grants you a personal, non-
|
||||
* exclusive, non-transferable license to copy, modify, and compile the
|
||||
* Software source code solely for use in connection with Cypress?s
|
||||
* integrated circuit products. Any reproduction, modification, translation,
|
||||
* compilation, or representation of this Software except as specified
|
||||
* above is prohibited without the express written permission of Cypress.
|
||||
*
|
||||
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
|
||||
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
|
||||
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. Cypress reserves the right to make
|
||||
* changes to the Software without notice. Cypress does not assume any
|
||||
* liability arising out of the application or use of the Software or any
|
||||
* product or circuit described in the Software. Cypress does not
|
||||
* authorize its products for use in any products where a malfunction or
|
||||
* failure of the Cypress product may reasonably be expected to result in
|
||||
* significant property damage, injury or death ("High Risk Product"). By
|
||||
* including Cypress's product in a High Risk Product, the manufacturer
|
||||
* of such system or application assumes all risk of such use and in doing
|
||||
* so agrees to indemnify Cypress against all liability.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __FLASH_QSPI_H__
|
||||
#define __FLASH_QSPI_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cy_pdl.h"
|
||||
|
||||
/* make it exported if used in TOC (cy_serial_flash_prog.c) */
|
||||
/* cy_stc_smif_block_config_t smifBlockConfig_sfdp; */
|
||||
|
||||
cy_en_smif_status_t qspi_init_sfdp(uint32_t smif_id);
|
||||
cy_en_smif_status_t qspi_init(cy_stc_smif_block_config_t *blk_config);
|
||||
cy_en_smif_status_t qspi_init_hardware(void);
|
||||
uint32_t qspi_get_prog_size(void);
|
||||
uint32_t qspi_get_erase_size(void);
|
||||
uint32_t qspi_get_mem_size(void);
|
||||
|
||||
SMIF_Type *qspi_get_device(void);
|
||||
cy_stc_smif_context_t *qspi_get_context(void);
|
||||
cy_stc_smif_mem_config_t *qspi_get_memory_config(int index);
|
||||
void qspi_dump_device(cy_stc_smif_mem_device_cfg_t *dev);
|
||||
|
||||
#endif /* __FLASH_QSPI_H__ */
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015 Runtime Inc
|
||||
* Copyright (c) 2020 Cypress Semiconductor Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
|
||||
#ifndef CY_FLASH_PSOC6_H_
|
||||
#define CY_FLASH_PSOC6_H_
|
||||
|
||||
#include "stddef.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#ifndef off_t
|
||||
typedef long int off_t;
|
||||
#endif
|
||||
|
||||
int psoc6_flash_read(off_t addr, void *data, size_t len);
|
||||
int psoc6_flash_write(off_t addr, const void *data, size_t len);
|
||||
int psoc6_flash_erase(off_t addr, size_t size);
|
||||
|
||||
int psoc6_flash_write_hal(uint8_t data[],
|
||||
uint32_t address,
|
||||
uint32_t len);
|
||||
#endif /* CY_FLASH_PSOC6_H_ */
|
|
@ -0,0 +1,64 @@
|
|||
/***************************************************************************//**
|
||||
* \file cy_smif_psoc6.h
|
||||
* \version 1.0
|
||||
*
|
||||
* \brief
|
||||
* This is the header file for PSoC6 SMIF driver adoption layer.
|
||||
*
|
||||
********************************************************************************
|
||||
* \copyright
|
||||
*
|
||||
* © 2019, Cypress Semiconductor Corporation
|
||||
* or a subsidiary of Cypress Semiconductor Corporation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* This software, including source code, documentation and related
|
||||
* materials ("Software"), is owned by Cypress Semiconductor
|
||||
* Corporation or one of its subsidiaries ("Cypress") and is protected by
|
||||
* and subject to worldwide patent protection (United States and foreign),
|
||||
* United States copyright laws and international treaty provisions.
|
||||
* Therefore, you may use this Software only as provided in the license
|
||||
* agreement accompanying the software package from which you
|
||||
* obtained this Software ("EULA").
|
||||
*
|
||||
* If no EULA applies, Cypress hereby grants you a personal, non-
|
||||
* exclusive, non-transferable license to copy, modify, and compile the
|
||||
* Software source code solely for use in connection with Cypress?s
|
||||
* integrated circuit products. Any reproduction, modification, translation,
|
||||
* compilation, or representation of this Software except as specified
|
||||
* above is prohibited without the express written permission of Cypress.
|
||||
*
|
||||
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
|
||||
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
|
||||
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. Cypress reserves the right to make
|
||||
* changes to the Software without notice. Cypress does not assume any
|
||||
* liability arising out of the application or use of the Software or any
|
||||
* product or circuit described in the Software. Cypress does not
|
||||
* authorize its products for use in any products where a malfunction or
|
||||
* failure of the Cypress product may reasonably be expected to result in
|
||||
* significant property damage, injury or death ("High Risk Product"). By
|
||||
* including Cypress's product in a High Risk Product, the manufacturer
|
||||
* of such system or application assumes all risk of such use and in doing
|
||||
* so agrees to indemnify Cypress against all liability.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CY_SMIF_PSOC6_H_
|
||||
#define CY_SMIF_PSOC6_H_
|
||||
|
||||
#include "stddef.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
#include "flash_qspi.h"
|
||||
|
||||
#ifndef off_t
|
||||
typedef long int off_t;
|
||||
#endif
|
||||
|
||||
int psoc6_smif_read(const struct flash_area *fap, off_t addr, void *data, size_t len);
|
||||
int psoc6_smif_write(const struct flash_area *fap, off_t addr, const void *data, size_t len);
|
||||
int psoc6_smif_erase(off_t addr, size_t size);
|
||||
|
||||
#endif /* CY_SMIF_PSOC6_H_ */
|
|
@ -30,6 +30,16 @@
|
|||
|
||||
#include <mcuboot_config/mcuboot_config.h>
|
||||
#include "cy_flash.h"
|
||||
#define FLASH_DEVICE_INDEX_MASK (0x7F)
|
||||
#define FLASH_DEVICE_GET_EXT_INDEX(n) ((n) & FLASH_DEVICE_INDEX_MASK)
|
||||
#define FLASH_DEVICE_EXTERNAL_FLAG (0x80)
|
||||
#define FLASH_DEVICE_INTERNAL_FLASH (0x7F)
|
||||
#define FLASH_DEVICE_EXTERNAL_FLASH(index) (FLASH_DEVICE_EXTERNAL_FLAG | index)
|
||||
|
||||
#ifndef CY_BOOT_EXTERNAL_DEVICE_INDEX
|
||||
/* assume first(one) SMIF device is used */
|
||||
#define CY_BOOT_EXTERNAL_DEVICE_INDEX (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -137,7 +147,9 @@ int flash_area_id_to_image_slot(int area_id);
|
|||
|
||||
int flash_area_id_from_multi_image_slot(int image_index, int slot);
|
||||
int flash_area_id_to_multi_image_slot(int image_index, int area_id);
|
||||
|
||||
#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
|
||||
int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret);
|
||||
#endif
|
||||
/*
|
||||
* Returns the value expected to be read when accesing any erased
|
||||
* flash byte.
|
||||
|
|
Loading…
Reference in New Issue