Initial commit
Initial commit.
This commit is contained in:
547
bootloader/mcuboot/boot/cypress/cy_flash_pal/cy_flash_map.c
Normal file
547
bootloader/mcuboot/boot/cypress/cy_flash_pal/cy_flash_map.c
Normal 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
|
||||
143
bootloader/mcuboot/boot/cypress/cy_flash_pal/cy_smif_psoc6.c
Normal file
143
bootloader/mcuboot/boot/cypress/cy_flash_pal/cy_smif_psoc6.c
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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_ */
|
||||
@@ -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__ */
|
||||
Reference in New Issue
Block a user