Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

View File

@@ -0,0 +1,547 @@
/*
* Copyright (c) 2018 Nordic Semiconductor ASA
* 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.
*/
/*******************************************************************************/
#ifdef MCUBOOT_HAVE_ASSERT_H
#include "mcuboot_config/mcuboot_assert.h"
#else
#include <assert.h>
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include "mcuboot_config/mcuboot_config.h"
#include "flash_map_backend/flash_map_backend.h"
#include <sysflash/sysflash.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.
*
* Pick a random device ID for it that's unlikely to collide with
* anything "real".
*/
#define FLASH_DEVICE_ID 111
#define FLASH_MAP_ENTRY_MAGIC 0xd00dbeef
#define FLASH_AREA_IMAGE_SECTOR_SIZE FLASH_AREA_IMAGE_SCRATCH_SIZE
#ifndef CY_BOOTLOADER_START_ADDRESS
#define CY_BOOTLOADER_START_ADDRESS (0x10000000)
#endif
#ifndef CY_BOOT_INTERNAL_FLASH_ERASE_VALUE
/* This is the value of internal flash bytes after an erase */
#define CY_BOOT_INTERNAL_FLASH_ERASE_VALUE (0x00)
#endif
#ifndef CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE
/* This is the value of external flash bytes after an erase */
#define CY_BOOT_EXTERNAL_FLASH_ERASE_VALUE (0xff)
#endif
#ifdef CY_FLASH_MAP_EXT_DESC
/* Nothing to be there when external FlashMap Descriptors are used */
#else
static struct flash_area bootloader =
{
.fa_id = FLASH_AREA_BOOTLOADER,
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_BOOTLOADER_START_ADDRESS,
.fa_size = CY_BOOT_BOOTLOADER_SIZE
};
static struct flash_area primary_1 =
{
.fa_id = FLASH_AREA_IMAGE_PRIMARY(0),
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE + CY_BOOT_BOOTLOADER_SIZE,
.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),
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
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 =
{
.fa_id = FLASH_AREA_IMAGE_PRIMARY(1),
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE,
.fa_size = CY_BOOT_PRIMARY_2_SIZE
};
static struct flash_area secondary_2 =
{
.fa_id = FLASH_AREA_IMAGE_SECONDARY(1),
/* it is for external flash memory
.fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX), */
#ifndef CY_BOOT_USE_EXTERNAL_FLASH
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE +\
CY_BOOT_PRIMARY_2_SIZE,
#else
.fa_device_id = FLASH_DEVICE_EXTERNAL_FLASH(CY_BOOT_EXTERNAL_DEVICE_INDEX),
.fa_off = CY_SMIF_BASE_MEM_OFFSET + 0x40000,
#endif
.fa_size = CY_BOOT_SECONDARY_2_SIZE
};
#endif
#endif
#ifdef MCUBOOT_SWAP_USING_SCRATCH
static struct flash_area scratch =
{
.fa_id = FLASH_AREA_IMAGE_SCRATCH,
.fa_device_id = FLASH_DEVICE_INTERNAL_FLASH,
#if (MCUBOOT_IMAGE_NUMBER == 1) /* if single-image */
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE,
#elif (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
.fa_off = CY_FLASH_BASE +\
CY_BOOT_BOOTLOADER_SIZE +\
CY_BOOT_PRIMARY_1_SIZE +\
CY_BOOT_SECONDARY_1_SIZE +\
CY_BOOT_PRIMARY_2_SIZE +\
CY_BOOT_SECONDARY_2_SIZE,
#endif
.fa_size = CY_BOOT_SCRATCH_SIZE
};
#endif
#ifdef CY_FLASH_MAP_EXT_DESC
/* Use external Flash Map Descriptors */
extern struct flash_area *boot_area_descs[];
#else
struct flash_area *boot_area_descs[] =
{
&bootloader,
&primary_1,
&secondary_1,
#if (MCUBOOT_IMAGE_NUMBER == 2) /* if dual-image */
&primary_2,
&secondary_2,
#endif
#ifdef MCUBOOT_SWAP_USING_SCRATCH
&scratch,
#endif
NULL
};
#endif
/* Returns device flash start based on supported fa_id */
int flash_device_base(uint8_t fd_id, uintptr_t *ret)
{
if (fd_id != FLASH_DEVICE_INTERNAL_FLASH) {
BOOT_LOG_ERR("invalid flash ID %d; expected %d",
fd_id, FLASH_DEVICE_INTERNAL_FLASH);
return -1;
}
*ret = CY_FLASH_BASE;
return 0;
}
/* Opens the area for use. id is one of the `fa_id`s */
int flash_area_open(uint8_t id, const struct flash_area **fa)
{
int ret = -1;
uint32_t i = 0;
while(NULL != boot_area_descs[i])
{
if(id == boot_area_descs[i]->fa_id)
{
*fa = boot_area_descs[i];
ret = 0;
break;
}
i++;
}
return ret;
}
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`
*/
int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
uint32_t len)
{
int rc = 0;
size_t addr;
/* 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;
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_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
rc = psoc6_smif_read(fa, addr, dst, len);
}
#endif
else
{
/* incorrect/non-existing flash device id */
rc = -1;
}
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`
*/
int flash_area_write(const struct flash_area *fa, uint32_t off,
const void *src, uint32_t len)
{
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)
{
uint32_t row_number = 0;
uint32_t row_addr = 0;
assert(!(len % CY_FLASH_SIZEOF_ROW));
assert(!(write_start_addr % 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 = 0; i < row_number; i++)
{
rc = Cy_Flash_WriteRow(row_addr, row_ptr);
row_addr += (uint32_t) CY_FLASH_SIZEOF_ROW;
row_ptr = row_ptr + CY_FLASH_SIZEOF_ROW / 4;
}
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
rc = psoc6_smif_write(fa, write_start_addr, src, len);
}
#endif
else
{
/* incorrect/non-existing flash device id */
rc = -1;
}
return (int) rc;
}
/*< Erases `len` bytes of flash memory at `off` */
int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
{
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)
{
int row_number = 0;
uint32_t row_addr = 0;
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)
{
rc = psoc6_smif_erase(erase_start_addr, len);
}
#endif
else
{
/* incorrect/non-existing flash device id */
rc = -1;
}
return (int) rc;
}
/*< Returns this `flash_area`s alignment */
uint32_t flash_area_align(const struct flash_area *fa)
{
int ret = -1;
if (fa->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
ret = CY_FLASH_ALIGN;
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
return qspi_get_prog_size();
}
#endif
else
{
/* incorrect/non-existing flash device id */
ret = -1;
}
return ret;
}
#ifdef MCUBOOT_USE_FLASH_AREA_GET_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)
{
(void)idx;
(void)cnt;
rc = 0;
}
#ifdef CY_BOOT_USE_EXTERNAL_FLASH
else if ((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
(void)idx;
(void)cnt;
rc = 0;
}
#endif
else
{
/* incorrect/non-existing flash device id */
rc = -1;
}
return rc;
}
#endif
/*
* This depends on the mappings defined in sysflash.h.
* MCUBoot uses continuous numbering for the primary slot, the secondary slot,
* and the scratch while zephyr might number it differently.
*/
int flash_area_id_from_multi_image_slot(int image_index, int slot)
{
switch (slot) {
case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
case 2: return FLASH_AREA_IMAGE_SCRATCH;
}
return -1; /* flash_area_open will fail on that */
}
int flash_area_id_from_image_slot(int slot)
{
return flash_area_id_from_multi_image_slot(0, slot);
}
int flash_area_id_to_multi_image_slot(int image_index, int area_id)
{
if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
return 0;
}
if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
return 1;
}
return -1;
}
uint8_t flash_area_erased_val(const struct flash_area *fap)
{
int ret = 0;
if (fap->fa_device_id == FLASH_DEVICE_INTERNAL_FLASH)
{
ret = CY_BOOT_INTERNAL_FLASH_ERASE_VALUE;
}
#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;
}
#endif
else
{
assert(false) ;
}
return ret ;
}
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
void *dst, uint32_t len)
{
uint8_t *mem_dest;
int rc;
mem_dest = (uint8_t *)dst;
rc = flash_area_read(fa, off, dst, len);
if (rc) {
return -1;
}
for (uint8_t i = 0; i < len; i++) {
if (mem_dest[i] != flash_area_erased_val(fa)) {
return 0;
}
}
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 = NULL;
while(NULL != boot_area_descs[i])
{
if(idx == boot_area_descs[i]->fa_id)
{
fa = boot_area_descs[i];
break;
}
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_BOOT_USE_EXTERNAL_FLASH
else if((fa->fa_device_id & FLASH_DEVICE_EXTERNAL_FLAG) == FLASH_DEVICE_EXTERNAL_FLAG)
{
/* implement for SMIF */
/* lets assume they are equal */
sector_size = CY_FLASH_SIZEOF_ROW;
}
#endif
else
{
rc = -1;
}
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);
addr = fa->fa_off;
for(i = 0; i < sectors_n; i++)
{
ret[i].fs_size = sector_size ;
ret[i].fs_off = addr ;
addr += sector_size ;
}
*cnt = sectors_n;
}
}
else
{
rc = -1;
}
return rc;
}
#endif

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,494 @@
/*
* 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) || \
defined(PSOC_062_1M))
#define CY_BOOTLOADER_SMIF_SS_CFG_NUM 4
#elif defined(PSOC_064_512K) || defined(PSOC_062_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;
}
void qspi_deinit(uint32_t smif_id)
{
Cy_SMIF_MemDeInit(QSPIPort);
Cy_SMIF_Disable(QSPIPort);
Cy_SysClk_ClkHfDisable(CY_SYSCLK_CLKHF_IN_CLKPATH2);
NVIC_DisableIRQ(smifIntConfig.intrSrc);
Cy_SysInt_DisconnectInterruptSource(smifIntConfig.intrSrc, smifIntConfig.cm0pSrc);
Cy_GPIO_Port_Deinit(qspi_SS_Configuration[smif_id-1].SS_Port);
Cy_GPIO_Port_Deinit(SCKPort);
Cy_GPIO_Port_Deinit(D0Port);
Cy_GPIO_Port_Deinit(D1Port);
Cy_GPIO_Port_Deinit(D2Port);
Cy_GPIO_Port_Deinit(D3Port);
}

View File

@@ -0,0 +1,70 @@
/***************************************************************************//**
* \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);
void qspi_deinit(uint32_t smif_id);
#endif /* __FLASH_QSPI_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

@@ -0,0 +1,195 @@
/*
* 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 __FLASH_MAP_BACKEND_H__
#define __FLASH_MAP_BACKEND_H__
#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
/**
*
* Provides abstraction of flash regions for type of use.
* I.e. dude where's my image?
*
* System will contain a map which contains flash areas. Every
* region will contain flash identifier, offset within flash and length.
*
* 1. This system map could be in a file within filesystem (Initializer
* must know/figure out where the filesystem is at).
* 2. Map could be at fixed location for project (compiled to code)
* 3. Map could be at specific place in flash (put in place at mfg time).
*
* Note that the map you use must be valid for BSP it's for,
* match the linker scripts when platform executes from flash,
* and match the target offset specified in download script.
*/
#include <inttypes.h>
/**
* @brief Structure describing an area on a flash device.
*
* Multiple flash devices may be available in the system, each of
* which may have its own areas. For this reason, flash areas track
* which flash device they are part of.
*/
struct flash_area {
/**
* This flash area's ID; unique in the system.
*/
uint8_t fa_id;
/**
* ID of the flash device this area is a part of.
*/
uint8_t fa_device_id;
uint16_t pad16;
/**
* This area's offset, relative to the beginning of its flash
* device's storage.
*/
uint32_t fa_off;
/**
* This area's size, in bytes.
*/
uint32_t fa_size;
};
static inline uint8_t flash_area_get_id(const struct flash_area *fa)
{
return fa->fa_id;
}
static inline uint8_t flash_area_get_device_id(const struct flash_area *fa)
{
return fa->fa_device_id;
}
static inline uint32_t flash_area_get_off(const struct flash_area *fa)
{
return fa->fa_off;
}
static inline uint32_t flash_area_get_size(const struct flash_area *fa)
{
return fa->fa_size;
}
/**
* @brief Structure describing a sector within a flash area.
*
* Each sector has an offset relative to the start of its flash area
* (NOT relative to the start of its flash device), and a size. A
* flash area may contain sectors with different sizes.
*/
struct flash_sector {
/**
* Offset of this sector, from the start of its flash area (not device).
*/
uint32_t fs_off;
/**
* Size of this sector, in bytes.
*/
uint32_t fs_size;
};
static inline uint32_t flash_sector_get_off(const struct flash_sector *fs)
{
return fs->fs_off;
}
static inline uint32_t flash_sector_get_size(const struct flash_sector *fs)
{
return fs->fs_size;
}
struct flash_map_entry {
uint32_t magic;
struct flash_area area;
unsigned int ref_count;
};
/*
* Retrieve a memory-mapped flash device's base address.
* On success, the address will be stored in the value pointed to by
* ret.
* Returns 0 on success, or an error code on failure.
*/
int flash_device_base(uint8_t fd_id, uintptr_t *ret);
/*< Opens the area for use. id is one of the `fa_id`s */
int flash_area_open(uint8_t id, const struct flash_area **);
void flash_area_close(const struct flash_area *);
/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */
int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
uint32_t len);
/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */
int flash_area_write(const struct flash_area *, uint32_t off,
const void *src, uint32_t len);
/*< Erases `len` bytes of flash memory at `off` */
int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
/*< Returns this `flash_area`s alignment */
uint32_t flash_area_align(const struct flash_area *);
/*< Initializes an array of flash_area elements for the slot's sectors */
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret);
/*< Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary) */
int flash_area_id_from_image_slot(int slot);
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.
*/
uint8_t flash_area_erased_val(const struct flash_area *fap);
/*
* Reads len bytes from off, and checks if the read data is erased.
*
* Returns 1 if erased, 0 if non-erased, and -1 on failure.
*/
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
void *dst, uint32_t len);
#endif /* __FLASH_MAP_BACKEND_H__ */