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:
Bohdan Kovalchuk 2020-05-26 08:04:24 -05:00 committed by Roman Okhrimenko
parent 50d24a5751
commit 0324f1b023
19 changed files with 1104 additions and 362 deletions

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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))

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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.