psa: Remove v8-M S targets

Remove PSA v8-M S target binaries will be built outside of Mbed OS and
added in as binaries which NS targets consume. Mbed OS no longer
implements PSA for v8-M targets, so there is no reason for it to build
PSA S targets.

Signed-off-by: Jaeden Amero <jaeden.amero@arm.com>
pull/12737/head
Jaeden Amero 2020-03-12 16:04:49 +00:00 committed by Jaeden Amero
parent 493a043528
commit 6b3a9cb4fa
125 changed files with 10 additions and 18792 deletions

View File

@ -49,9 +49,6 @@ TLS_SRC := \
# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For
# example PSA Crypto or PSA Secure Time implementations
TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/COMPONENT_PSA_SRV_IMPL
# COMPONENT_SPE - Include code that compiles ONLY to the SPE image and never
# compiles to the NSPE image
TARGET_SPE:=$(TARGET_PREFIX)/platform/COMPONENT_SPE
# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never
# compiles to the SPE image
TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE
@ -88,15 +85,12 @@ rsync:
#
# Copying Mbed Crypto into Mbed OS...
rm -rf $(TARGET_SRV_IMPL)
rm -rf $(TARGET_SPE)
rm -rf $(TARGET_SRC)
mkdir -p $(TARGET_SRV_IMPL)
mkdir -p $(TARGET_SPE)
mkdir -p $(TARGET_NSPE)
rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/
rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h
rsync -a --delete $(CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/
rsync -a --delete $(CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/
rsync -a --delete $(CRYPTO_DIR)/library/*.c $(TARGET_SRC)/
@ -135,4 +129,3 @@ clean:
rm -rf $(TARGET_SRC)
rm -rf $(CRYPTO_DIR)
rm -rf $(TARGET_SRV_IMPL)
rm -rf $(TARGET_SPE)

View File

@ -1,124 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
#ifndef __RTE_DEVICE_H
#define __RTE_DEVICE_H
// <e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
// <i> Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC
#define RTE_ISRAM0_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
// <i> Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC
#define RTE_ISRAM1_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
// <i> Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC
#define RTE_ISRAM2_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM3_MPC]
// <i> Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC
#define RTE_ISRAM3_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_SRAM3_MPC]
// <e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
// <i> Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC
#define RTE_CODE_SRAM_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
// <e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
// <i> Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC
#define RTE_QSPI_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
#define RTE_USART0 1
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
#define RTE_USART1 1
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
// <i> Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC
#define RTE_AHB_PPC0 1
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
// <i> Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP0 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
// <i> Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP1 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
// <i> Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP2 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
// <i> Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP3 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
// <i> Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC
#define RTE_APB_PPC0 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
// <i> Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC
#define RTE_APB_PPC1 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
// <i> Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC
#define RTE_APB_PPCEXP0 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
// <i> Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC
#define RTE_APB_PPCEXP1 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
// <i> Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC
#define RTE_APB_PPCEXP2 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
// <i> Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC
#define RTE_APB_PPCEXP3 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
// <e> FLASH (Flash Memory) [Driver_FLASH0]
// <i> Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH
#define RTE_FLASH0 1
// </e> FLASH (Flash Memory) [Driver_FLASH0]
#endif /* __RTE_DEVICE_H */

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_DRIVER_CONFIG_H__
#define __CMSIS_DRIVER_CONFIG_H__
#include "device_cfg.h"
#include "platform_retarget_dev.h"
#include "platform_retarget_pins.h"
#include "RTE_Device.h"
#include "target_cfg.h"
#define UART0_DEV UART0_PL011_DEV_NS
#define UART1_DEV UART1_PL011_DEV_NS
#define FLASH0_DEV MT25QL_DEV_NS
#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S
#define MPC_ISRAM1_DEV MPC_ISRAM1_DEV_S
#define MPC_ISRAM2_DEV MPC_ISRAM2_DEV_S
#define MPC_ISRAM3_DEV MPC_ISRAM3_DEV_S
#define MPC_CODE_SRAM_DEV MPC_CODE_SRAM_DEV_S
#define MPC_QSPI_DEV MPC_QSPI_DEV_S
#define AHB_PPC0_DEV AHB_PPC0_DEV_S
#define AHB_PPCEXP0_DEV AHB_PPCEXP0_DEV_S
#define AHB_PPCEXP1_DEV AHB_PPCEXP1_DEV_S
#define AHB_PPCEXP2_DEV AHB_PPCEXP2_DEV_S
#define AHB_PPCEXP3_DEV AHB_PPCEXP3_DEV_S
#define APB_PPC0_DEV APB_PPC0_DEV_S
#define APB_PPC1_DEV APB_PPC1_DEV_S
#define APB_PPCEXP0_DEV APB_PPCEXP0_DEV_S
#define APB_PPCEXP1_DEV APB_PPCEXP1_DEV_S
#define APB_PPCEXP2_DEV APB_PPCEXP2_DEV_S
#define APB_PPCEXP3_DEV APB_PPCEXP3_DEV_S
#define MUSCA_A1_SCC_DEV MUSCA_A1_SCC_DEV_S
#endif /* __CMSIS_DRIVER_CONFIG_H__ */

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2013-2016 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Jan 2014
* $Revision: V2.00
*
* Project: Common Driver definitions
*/
/* History:
* Version 2.00
* Changed prefix ARM_DRV -> ARM_DRIVER
* Added General return codes definitions
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.00
* Initial release
*/
#ifndef __DRIVER_COMMON_H
#define __DRIVER_COMMON_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor))
/**
\brief Driver Version
*/
typedef struct _ARM_DRIVER_VERSION {
uint16_t api; ///< API version
uint16_t drv; ///< Driver version
} ARM_DRIVER_VERSION;
/* General return codes */
#define ARM_DRIVER_OK 0 ///< Operation succeeded
#define ARM_DRIVER_ERROR -1 ///< Unspecified error
#define ARM_DRIVER_ERROR_BUSY -2 ///< Driver is busy
#define ARM_DRIVER_ERROR_TIMEOUT -3 ///< Timeout occurred
#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported
#define ARM_DRIVER_ERROR_PARAMETER -5 ///< Parameter error
#define ARM_DRIVER_ERROR_SPECIFIC -6 ///< Start of driver specific errors
/**
\brief General power states
*/
typedef enum _ARM_POWER_STATE {
ARM_POWER_OFF, ///< Power off: no operation possible
ARM_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events
ARM_POWER_FULL ///< Power on: full operation at maximum performance
} ARM_POWER_STATE;
#endif /* __DRIVER_COMMON_H */

View File

@ -1,153 +0,0 @@
/*
* Copyright (c) 2016-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DRIVER_MPC_H
#define __DRIVER_MPC_H
#include "Driver_Common.h"
/* API version */
#define ARM_MPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
/* Error code returned by the driver functions */
#define ARM_MPC_ERR_NOT_INIT (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< MPC not initialized */
#define ARM_MPC_ERR_NOT_IN_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Address does not belong to a range controlled by the MPC */
#define ARM_MPC_ERR_NOT_ALIGNED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Address is not aligned on the block size of this MPC */
#define ARM_MPC_ERR_INVALID_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given address range to configure is invalid
#define ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given range cannot be accessed with the wanted security attributes */
#define ARM_MPC_ERR_UNSPECIFIED (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Unspecified error */
/* Security attribute used in various place of the API */
typedef enum _ARM_MPC_SEC_ATTR {
ARM_MPC_ATTR_SECURE, ///< Secure attribute
ARM_MPC_ATTR_NONSECURE, ///< Non-secure attribute
/* Used when getting the configuration of a memory range and some blocks are
* secure whereas some other are non secure */
ARM_MPC_ATTR_MIXED, ///< Mixed attribute
} ARM_MPC_SEC_ATTR;
/* Function documentation */
/**
\fn ARM_DRIVER_VERSION ARM_MPC_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn int32_t ARM_MPC_Initialize (void)
\brief Initialize MPC Interface.
\return Returns error code.
\fn int32_t ARM_MPC_Uninitialize (void)
\brief De-initialize MPC Interface. The controlled memory region
should not be accessed after a call to this function, as
it is allowed to configure everything to be secure (to
prevent information leak for example).
\return Returns error code.
\fn int32_t ARM_MPC_GetBlockSize (uint32_t* blk_size)
\brief Get the block size of the MPC. All regions must be aligned
on this block size (base address and limit+1 address).
\param[out] blk_size: The block size in bytes.
\return Returns error code.
\fn int32_t ARM_MPC_GetCtrlConfig (uint32_t* ctrl_val)
\brief Get some information on how the MPC IP is configured.
\param[out] ctrl_val: MPC control configuration
\return Returns error code.
\fn int32_t ARM_MPC_SetCtrlConfig (uint32_t ctrl)
\brief Set new control configuration for the MPC IP.
\param[in] ctrl: New control configuration.
\return Returns error code.
\fn int32_t ARM_MPC_ConfigRegion (uintptr_t base,
uintptr_t limit,
ARM_MPC_SEC_ATTR attr)
\brief Configure a memory region (base and limit included).
Both base and limit addresses must belong to the same
memory range, and this range must be managed by this MPC.
Also, some ranges are only allowed to be configured as
secure/non-secure, because of hardware requirements
(security aliases), and only a relevant security attribute
is therefore allowed for such ranges.
\param[in] base: Base address of the region to configure. This
bound is included in the configured region.
This must be aligned on the block size of this MPC.
\param[in] limit: Limit address of the region to configure. This
bound is included in the configured region.
Limit+1 must be aligned on the block size of this MPC.
\param[in] attr: Wanted security attribute of the region.
\return Returns error code.
\fn int32_t ARM_MPC_GetRegionConfig (uintptr_t base,
uintptr_t limit,
ARM_MPC_SEC_ATTR *attr)
\brief Gets a memory region (base and limit included).
\param[in] base: Base address of the region to poll. This
bound is included. It does not need to be aligned
in any way.
\param[in] limit: Limit address of the region to poll. This
bound is included. (limit+1) does not need to be aligned
in any way.
\param[out] attr: Security attribute of the region.
If the region has mixed secure/non-secure,
a special value is returned (\ref ARM_MPC_SEC_ATTR).
In case base and limit+1 addresses are not aligned on
the block size, the enclosing region with base and
limit+1 aligned on block size will be queried.
In case of early termination of the function (error), the
security attribute will be set to ARM_MPC_ATTR_MIXED.
\return Returns error code.
\fn int32_t ARM_MPC_EnableInterrupt (void)
\brief Enable MPC interrupt.
\return Returns error code.
\fn void ARM_MPC_DisableInterrupt (void)
\brief Disable MPC interrupt.
\fn void ARM_MPC_ClearInterrupt (void)
\brief Clear MPC interrupt.
\fn uint32_t ARM_MPC_InterruptState (void)
\brief MPC interrupt state.
\return Returns 1 if the interrupt is active, 0 otherwise.
\fn int32_t ARM_MPC_LockDown (void)
\brief Lock down the MPC configuration.
\return Returns error code.
*/
/**
* \brief Access structure of the MPC Driver.
*/
typedef struct _ARM_DRIVER_MPC {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_MPC_GetVersion : Get driver version.
int32_t (*Initialize) (void); ///< Pointer to \ref ARM_MPC_Initialize : Initialize the MPC Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_MPC_Uninitialize : De-initialize the MPC Interface.
int32_t (*GetBlockSize) (uint32_t* blk_size); ///< Pointer to \ref ARM_MPC_GetBlockSize : Get MPC block size
int32_t (*GetCtrlConfig) (uint32_t* ctrl_val); ///< Pointer to \ref ARM_MPC_GetCtrlConfig : Get the MPC control configuration flags.
int32_t (*SetCtrlConfig) (uint32_t ctrl); ///< Pointer to \ref ARM_MPC_SetCtrlConfig : Set the MPC control configuration flags.
int32_t (*ConfigRegion) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR attr); ///< Pointer to \ref ARM_MPC_ConfigRegion : Configure a region using the driver for the specific MPC.
int32_t (*GetRegionConfig) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR *attr); ///< Pointer to \ref ARM_MPC_GetRegionConfig : Get the configuration of a specific region on this MPC.
int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_MPC_EnableInterrupt : Enable MPC interrupt.
void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_MPC_DisableInterrupt : Disable MPC interrupt.
void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_MPC_ClearInterrupt : Clear MPC interrupt.
uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_MPC_InterruptState : MPC interrupt State.
int32_t (*LockDown) (void); ///< Pointer to \ref ARM_MPC_LockDown : Lock down the MPC configuration.
} const ARM_DRIVER_MPC;
#endif /* __DRIVER_MPC_H */

View File

@ -1,969 +0,0 @@
/*
* Copyright (c) 2016-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Driver_PPC.h"
#include "cmsis.h"
#include "cmsis_driver_config.h"
#include "RTE_Device.h"
/* Driver version */
#define ARM_PPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_PPC_API_VERSION,
ARM_PPC_DRV_VERSION
};
static ARM_DRIVER_VERSION ARM_PPC_GetVersion(void)
{
return DriverVersion;
}
#if (RTE_AHB_PPC0)
/* AHB PPC0 Driver wrapper functions */
static int32_t AHB_PPC0_Initialize(void)
{
ppc_sse200_init(&AHB_PPC0_DEV, AHB_PPC0);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPC0_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t AHB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPC0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPC0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPC0_DEV, periph);
}
static uint32_t AHB_PPC0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPC0_DEV, periph);
}
static int32_t AHB_PPC0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPC0_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPC0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPC0_DEV);
}
static void AHB_PPC0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPC0_DEV);
}
static uint32_t AHB_PPC0_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPC0_DEV);
}
/* AHB PPC0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPC0;
ARM_DRIVER_PPC Driver_AHB_PPC0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPC0_Initialize,
.Uninitialize = AHB_PPC0_Uninitialize,
.ConfigPeriph = AHB_PPC0_ConfigPeriph,
.IsPeriphSecure = AHB_PPC0_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPC0_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPC0_EnableInterrupt,
.DisableInterrupt = AHB_PPC0_DisableInterrupt,
.ClearInterrupt = AHB_PPC0_ClearInterrupt,
.InterruptState = AHB_PPC0_InterruptState
};
#endif /* RTE_AHB_PPC0 */
#if (RTE_AHB_PPCEXP0)
/* AHB PPCEXP0 Driver wrapper functions */
static int32_t AHB_PPCEXP0_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP0_DEV, AHB_PPC_EXP0);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP0_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP0_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP0_DEV, periph);
}
static uint32_t AHB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP0_DEV, periph);
}
static int32_t AHB_PPCEXP0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP0_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP0_DEV);
}
static void AHB_PPCEXP0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP0_DEV);
}
static uint32_t AHB_PPCEXP0_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP0_DEV);
}
/* AHB PPCEXP0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0;
ARM_DRIVER_PPC Driver_AHB_PPCEXP0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP0_Initialize,
.Uninitialize = AHB_PPCEXP0_Uninitialize,
.ConfigPeriph = AHB_PPCEXP0_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP0_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP0_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP0_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP0_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP0_ClearInterrupt,
.InterruptState = AHB_PPCEXP0_InterruptState
};
#endif /* RTE_AHB_PPCEXP0 */
#if (RTE_AHB_PPCEXP1)
/* AHB PPCEXP1 Driver wrapper functions */
static int32_t AHB_PPCEXP1_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP1_DEV, AHB_PPC_EXP1);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP1_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP1_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP1_DEV, periph);
}
static uint32_t AHB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP1_DEV, periph);
}
static int32_t AHB_PPCEXP1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP1_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP1_DEV);
}
static void AHB_PPCEXP1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP1_DEV);
}
static uint32_t AHB_PPCEXP1_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP1_DEV);
}
/* AHB PPCEXP1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP1;
ARM_DRIVER_PPC Driver_AHB_PPCEXP1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP1_Initialize,
.Uninitialize = AHB_PPCEXP1_Uninitialize,
.ConfigPeriph = AHB_PPCEXP1_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP1_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP1_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP1_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP1_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP1_ClearInterrupt,
.InterruptState = AHB_PPCEXP1_InterruptState
};
#endif /* RTE_AHB_PPCEXP1 */
#if (RTE_AHB_PPCEXP2)
/* AHB PPCEXP2 Driver wrapper functions */
static int32_t AHB_PPCEXP2_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP2_DEV, AHB_PPC_EXP2);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP2_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP2_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP2_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP2_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP2_DEV, periph);
}
static uint32_t AHB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP2_DEV, periph);
}
static int32_t AHB_PPCEXP2_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP2_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP2_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP2_DEV);
}
static void AHB_PPCEXP2_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP2_DEV);
}
static uint32_t AHB_PPCEXP2_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP2_DEV);
}
/* AHB PPCEXP2 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP2;
ARM_DRIVER_PPC Driver_AHB_PPCEXP2 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP2_Initialize,
.Uninitialize = AHB_PPCEXP2_Uninitialize,
.ConfigPeriph = AHB_PPCEXP2_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP2_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP2_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP2_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP2_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP2_ClearInterrupt,
.InterruptState = AHB_PPCEXP2_InterruptState
};
#endif /* RTE_AHB_PPCEXP2 */
#if (RTE_AHB_PPCEXP3)
/* AHB PPCEXP3 Driver wrapper functions */
static int32_t AHB_PPCEXP3_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP3_DEV, AHB_PPC_EXP3);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP3_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP3_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP3_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP3_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP3_DEV, periph);
}
static uint32_t AHB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP3_DEV, periph);
}
static int32_t AHB_PPCEXP3_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP3_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP3_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP3_DEV);
}
static void AHB_PPCEXP3_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP3_DEV);
}
static uint32_t AHB_PPCEXP3_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP3_DEV);
}
/* AHB PPCEXP3 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP3;
ARM_DRIVER_PPC Driver_AHB_PPCEXP3 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP3_Initialize,
.Uninitialize = AHB_PPCEXP3_Uninitialize,
.ConfigPeriph = AHB_PPCEXP3_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP3_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP3_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP3_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP3_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP3_ClearInterrupt,
.InterruptState = AHB_PPCEXP3_InterruptState
};
#endif /* RTE_AHB_PPCEXP3 */
#if (RTE_APB_PPC0)
/* APB PPC0 Driver wrapper functions */
static int32_t APB_PPC0_Initialize(void)
{
ppc_sse200_init(&APB_PPC0_DEV, APB_PPC0);
return ARM_DRIVER_OK;
}
static int32_t APB_PPC0_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t APB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPC0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPC0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPC0_DEV, periph);
}
static uint32_t APB_PPC0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPC0_DEV, periph);
}
static int32_t APB_PPC0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPC0_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPC0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPC0_DEV);
}
static void APB_PPC0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPC0_DEV);
}
static uint32_t APB_PPC0_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPC0_DEV);
}
/* APB PPC0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPC0;
ARM_DRIVER_PPC Driver_APB_PPC0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPC0_Initialize,
.Uninitialize = APB_PPC0_Uninitialize,
.ConfigPeriph = APB_PPC0_ConfigPeriph,
.IsPeriphSecure = APB_PPC0_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPC0_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPC0_EnableInterrupt,
.DisableInterrupt = APB_PPC0_DisableInterrupt,
.ClearInterrupt = APB_PPC0_ClearInterrupt,
.InterruptState = APB_PPC0_InterruptState
};
#endif /* RTE_APB_PPC0 */
#if (RTE_APB_PPC1)
/* APB PPC1 Driver wrapper functions */
static int32_t APB_PPC1_Initialize(void)
{
ppc_sse200_init(&APB_PPC1_DEV, APB_PPC1);
return ARM_DRIVER_OK;
}
static int32_t APB_PPC1_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t APB_PPC1_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPC1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPC1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPC1_DEV, periph);
}
static uint32_t APB_PPC1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPC1_DEV, periph);
}
static int32_t APB_PPC1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPC1_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPC1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPC1_DEV);
}
static void APB_PPC1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPC1_DEV);
}
static uint32_t APB_PPC1_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPC1_DEV);
}
/* APB PPC1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPC1;
ARM_DRIVER_PPC Driver_APB_PPC1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPC1_Initialize,
.Uninitialize = APB_PPC1_Uninitialize,
.ConfigPeriph = APB_PPC1_ConfigPeriph,
.IsPeriphSecure = APB_PPC1_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPC1_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPC1_EnableInterrupt,
.DisableInterrupt = APB_PPC1_DisableInterrupt,
.ClearInterrupt = APB_PPC1_ClearInterrupt,
.InterruptState = APB_PPC1_InterruptState
};
#endif /* RTE_APB_PPC1 */
#if (RTE_APB_PPCEXP0)
/* APB PPCEXP0 Driver wrapper functions */
static int32_t APB_PPCEXP0_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP0_DEV, APB_PPC_EXP0);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP0_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP0_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP0_DEV, periph);
}
static uint32_t APB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP0_DEV, periph);
}
static int32_t APB_PPCEXP0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP0_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP0_DEV);
}
static void APB_PPCEXP0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP0_DEV);
}
static uint32_t APB_PPCEXP0_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP0_DEV);
}
/* APB PPCEXP0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP0;
ARM_DRIVER_PPC Driver_APB_PPCEXP0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP0_Initialize,
.Uninitialize = APB_PPCEXP0_Uninitialize,
.ConfigPeriph = APB_PPCEXP0_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP0_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP0_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP0_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP0_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP0_ClearInterrupt,
.InterruptState = APB_PPCEXP0_InterruptState
};
#endif /* RTE_APB_PPCEXP0 */
#if (RTE_APB_PPCEXP1)
/* APB PPCEXP1 Driver wrapper functions */
static int32_t APB_PPCEXP1_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP1_DEV, APB_PPC_EXP1);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP1_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP1_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP1_DEV, periph);
}
static uint32_t APB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP1_DEV, periph);
}
static int32_t APB_PPCEXP1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP1_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP1_DEV);
}
static void APB_PPCEXP1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP1_DEV);
}
static uint32_t APB_PPCEXP1_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP1_DEV);
}
/* APB PPCEXP1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP1;
ARM_DRIVER_PPC Driver_APB_PPCEXP1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP1_Initialize,
.Uninitialize = APB_PPCEXP1_Uninitialize,
.ConfigPeriph = APB_PPCEXP1_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP1_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP1_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP1_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP1_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP1_ClearInterrupt,
.InterruptState = APB_PPCEXP1_InterruptState
};
#endif /* RTE_APB_PPCEXP1 */
#if (RTE_APB_PPCEXP2)
/* APB PPCEXP2 Driver wrapper functions */
static int32_t APB_PPCEXP2_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP2_DEV, APB_PPC_EXP2);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP2_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP2_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP2_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP2_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP2_DEV, periph);
}
static uint32_t APB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP2_DEV, periph);
}
static int32_t APB_PPCEXP2_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP2_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP2_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP2_DEV);
}
static void APB_PPCEXP2_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP2_DEV);
}
static uint32_t APB_PPCEXP2_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP2_DEV);
}
/* APB PPCEXP2 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP2;
ARM_DRIVER_PPC Driver_APB_PPCEXP2 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP2_Initialize,
.Uninitialize = APB_PPCEXP2_Uninitialize,
.ConfigPeriph = APB_PPCEXP2_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP2_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP2_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP2_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP2_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP2_ClearInterrupt,
.InterruptState = APB_PPCEXP2_InterruptState
};
#endif /* RTE_APB_PPCEXP2 */
#if (RTE_APB_PPCEXP3)
/* APB PPCEXP3 Driver wrapper functions */
static int32_t APB_PPCEXP3_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP3_DEV, APB_PPC_EXP3);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP3_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP3_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP3_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP3_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP3_DEV, periph);
}
static uint32_t APB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP3_DEV, periph);
}
static int32_t APB_PPCEXP3_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP3_DEV);
if( ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP3_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP3_DEV);
}
static void APB_PPCEXP3_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP3_DEV);
}
static uint32_t APB_PPCEXP3_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP3_DEV);
}
/* APB PPCEXP3 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP3;
ARM_DRIVER_PPC Driver_APB_PPCEXP3 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP3_Initialize,
.Uninitialize = APB_PPCEXP3_Uninitialize,
.ConfigPeriph = APB_PPCEXP3_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP3_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP3_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP3_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP3_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP3_ClearInterrupt,
.InterruptState = APB_PPCEXP3_InterruptState
};
#endif /* RTE_APB_PPCEXP3 */

View File

@ -1,116 +0,0 @@
/*
* Copyright (c) 2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_PPC_DRV_H__
#define __CMSIS_PPC_DRV_H__
#include "Driver_Common.h"
/* API version */
#define ARM_PPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
/* Security attribute used to configure the peripheral */
typedef enum _ARM_PPC_SecAttr {
ARM_PPC_SECURE_ONLY, ///< Secure access
ARM_PPC_NONSECURE_ONLY, ///< Non-secure access
} ARM_PPC_SecAttr;
/* Privilege attribute used to configure the peripheral */
typedef enum _ARM_PPC_PrivAttr {
ARM_PPC_PRIV_AND_NONPRIV, ///< Privilege and non-privilege access
ARM_PPC_PRIV_ONLY, ///< Privilege only access
} ARM_PPC_PrivAttr;
/* Function documentation */
/**
\fn ARM_DRIVER_VERSION ARM_PPC_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn int32_t ARM_PPC_Initialize (void)
\brief Initialize PPC Interface.
\return Returns ARM error code.
\fn int32_t ARM_PPC_Uninitialize (void)
\brief De-initialize MPC Interface.
\return Returns ARM error code.
\fn int32_t ARM_PPC_ConfigPeriph (uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
\brief Configures a peripheral controlled by the given PPC.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
\param[in] sec_attr: Secure attribute value.
\param[in] priv_attr: Privilege attrivute value.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns ARM error code.
\fn int32_t ARM_PPC_IsPeriphSecure (uint8_t periph)
\brief Check if the peripheral is configured to be secure.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns 1 if the peripheral is configured as secure,
0 for non-secure.
\fn uint32_t ARM_PPC_IsPeriphPrivOnly (uint8_t periph)
\brief Check if the peripheral is configured to be privilege only.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns 1 if the peripheral is configured as privilege access
only, 0 for privilege and unprivilege access mode.
\fn int32_t ARM_PPC_EnableInterrupt (void)
\brief Enable PPC interrupt.
\return Returns ARM error code.
\fn void ARM_PPC_DisableInterrupt (void)
\brief Disable PPC interrupt.
\fn void ARM_PPC_ClearInterrupt (void)
\brief Clear PPC interrupt.
\fn int32_t ARM_PPC_InterruptState (void)
\brief PPC interrupt state.
\return Returns 1 if the interrupt is active, 0 otherwise.
*/
/**
* \brief Access structure of the MPC Driver.
*/
typedef struct _ARM_DRIVER_PPC {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_PPC_GetVersion : Get driver version.
int32_t (*Initialize) (void); ///< Pointer to \ref ARM_PPC_Initialize : Initialize the PPC Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_PPC_Uninitialize : De-initialize the PPC Interface.
int32_t (*ConfigPeriph) (uint8_t periph, ARM_PPC_SecAttr sec_attr, ARM_PPC_PrivAttr priv_attr); ///< Pointer to \ref ARM_PPC_ConfigPeriph : Configure a peripheral controlled by the PPC.
uint32_t (*IsPeriphSecure) (uint8_t periph); ///< Pointer to \ref IsPeriphSecure : Check if the peripheral is configured to be secure.
uint32_t (*IsPeriphPrivOnly) (uint8_t periph); ///< Pointer to \ref IsPeriphPrivOnly : Check if the peripheral is configured to be privilege only.
int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_PPC_EnableInterrupt : Enable PPC interrupt.
void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_PPC_DisableInterrupt : Disable PPC interrupt.
void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_PPC_ClearInterrupt : Clear PPC interrupt.
uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_PPC_InterruptState : PPC interrupt State.
} const ARM_DRIVER_PPC;
#endif /* __CMSIS_PPC_DRV_H__ */

View File

@ -1,944 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
/* Use memcpy function */
#include <string.h>
#include "mt25ql_flash_lib.h"
/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
/** Getter bit manipulation macro */
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
#define BITS_PER_WORD 32U
#define BYTES_PER_WORD 4U
#define ARG_NOT_USED 0
#define ARG_PTR_NOT_USED NULL
/** MT25QL used command */
#define WRITE_ENABLE_CMD 0x06U
#define READ_ENHANCED_VOLATILE_CFG_REG_CMD 0x65U
#define WRITE_ENHANCED_VOLATILE_CFG_REG_CMD 0x61U
#define READ_VOLATILE_CFG_REG_CMD 0x85U
#define WRITE_VOLATILE_CFG_REG_CMD 0x81U
#define READ_FLAG_STATUS_REG_CMD 0x70U
#define SUBSECTOR_ERASE_32KB_CMD 0x52U
#define SUBSECTOR_ERASE_4KB_CMD 0x20U
#define SECTOR_ERASE_CMD 0xD8U
#define BULK_ERASE_CMD 0xC7U
/*
* The baud rate divisor in \ref mt25ql_dev_t needs to be configured adequately
* to handle those commands.
*/
#define QUAD_OUTPUT_FAST_READ_CMD 0x6BU
#define FAST_READ_CMD 0x0BU
#define READ_CMD 0x03U
#define QUAD_INPUT_FAST_PROGRAM_CMD 0x32U
#define PAGE_PROGRAM_CMD 0x02U
/** MT25QL Enhanced Volatile Configuration Register access */
#define ENHANCED_VOLATILE_CFG_REG_LEN 1U
#define ENHANCED_VOLATILE_CFG_REG_QSPI_POS 7U
#define ENHANCED_VOLATILE_CFG_REG_DSPI_POS 6U
/** MT25QL Volatile Configuration Register access */
#define VOLATILE_CFG_REG_LEN 1U
#define VOLATILE_CFG_REG_DUMMY_CYCLES_POS 4U
#define VOLATILE_CFG_REG_DUMMY_CYCLES_BITS 4U
/** MT25QL Flag Status Register access */
#define FLAG_STATUS_REG_LEN 1U
#define FLAG_STATUS_REG_READY_POS 7U
/*
* 8 is the minimal number of dummy clock cycles needed to reach the maximal
* frequency of the Quad Output Fast Read Command.
*/
#define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES 8U
#define FAST_READ_DUMMY_CYCLES 8U
#define DEFAULT_READ_DUMMY_CYCLES 0U
#define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES 0U
#define PAGE_PROGRAM_DUMMY_CYCLES 0U
/* Only up to 8 bytes can be read or written using the Flash commands. */
#define CMD_DATA_MAX_SIZE 8U
/**
* \brief Change specific bits in a 32 bits word.
*
* \param[in,out] word Pointer of the word to change
* \param[in] bits bits_length bits to put at bits_pos in the word
* pointed
* \param[in] bits_length Number of bits to change
* \param[in] bits_pos Position of the bits to change
*
* \note This function will do nothing if the parameters given are incorrect:
* * word is NULL
* * bits_length + bits_pos > 32
* * bits_length is 0
*/
static void change_bits_in_word(volatile uint32_t *word,
uint32_t bits,
uint32_t bits_length,
uint32_t bits_pos)
{
uint32_t mask;
if ((word == NULL) ||
((bits_length + bits_pos) > BITS_PER_WORD) ||
(bits_length == 0U)) {
/* Silently fail */
return;
}
/* Change all the bits */
if (bits_length == BITS_PER_WORD) {
*word = bits;
return;
}
mask = ((1U << bits_length) - 1);
/*
* We change the bits in three steps:
* - clear bits_length bits with zeroes at bits_pos in the word
* - mask bits in case it contains more than bits_length bits
* - set the new bits in the cleared word
* Because the data pointed by word is only read once, the data will still
* be coherent after an interruption that changes it.
*/
*word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
}
/**
* \brief Send the Write Enable command, needed before any write.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*/
static void send_write_enable(struct mt25ql_dev_t* dev)
{
qspi_ip6514e_send_simple_cmd(dev->controller, WRITE_ENABLE_CMD);
}
/**
* \brief Set SPI mode on the flash device and on the controller.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] spi_mode SPI mode to be set on flash device and controller
* \ref qspi_ip6514e_spi_mode_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev,
enum qspi_ip6514e_spi_mode_t spi_mode)
{
uint8_t enhanced_volatile_cfg_reg = 0;
enum qspi_ip6514e_error_t controller_error;
/* Read the Enhanced Volatile Configuration Register, modify it according
* to the requested SPI mode then write back the modified value to the
* register. This will activate the SPI mode on the flash side.
*/
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
READ_ENHANCED_VOLATILE_CFG_REG_CMD,
&enhanced_volatile_cfg_reg,
ENHANCED_VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed for
this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
switch(spi_mode) {
case QSPI_IP6514E_SPI_MODE:
/* Disable the Dual- and Quad-SPI modes.
* Clearing the bit enables the mode, setting it disables it.
*/
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
case QSPI_IP6514E_DSPI_MODE:
/* Disable the Quad-SPI mode and activate DSPI mode.
* Clearing the bit enables the mode, setting it disables it.
*/
CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
case QSPI_IP6514E_QSPI_MODE:
/* Disable the Dual-SPI mode and activate QSPI mode.
* Clearing the bit enables the mode, setting it disables it.
*/
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
WRITE_ENHANCED_VOLATILE_CFG_REG_CMD,
&enhanced_volatile_cfg_reg,
ENHANCED_VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed for
this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Activate the requested SPI mode on the controller side as well. */
controller_error = qspi_ip6514e_set_spi_mode(dev->controller,
spi_mode,
spi_mode,
spi_mode);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
/**
* \brief Change the number of dummy clock cycles subsequent to all FAST READ
* commands.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] dummy_cycles Dummy clock cycles to set
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t change_dummy_cycles(struct mt25ql_dev_t* dev,
uint32_t dummy_cycles)
{
uint32_t volatile_cfg_reg = 0;
enum qspi_ip6514e_error_t controller_error;
/*
* Changes the number of dummy cycles in the Volatile Configuration
* Register.
*/
controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
READ_VOLATILE_CFG_REG_CMD,
&volatile_cfg_reg,
VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed
for this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
change_bits_in_word(&volatile_cfg_reg,
dummy_cycles,
VOLATILE_CFG_REG_DUMMY_CYCLES_BITS,
VOLATILE_CFG_REG_DUMMY_CYCLES_POS);
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
WRITE_VOLATILE_CFG_REG_CMD,
&volatile_cfg_reg,
VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed
for this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
/**
* \brief Wait until the current program/erase is finished.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t wait_program_or_erase_complete(
struct mt25ql_dev_t* dev)
{
enum qspi_ip6514e_error_t controller_error;
uint8_t flag_status_reg = 0;
/* Wait until the ready bit of the Flag Status Register is set */
while (!GET_BIT(flag_status_reg, FLAG_STATUS_REG_READY_POS)) {
controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
READ_FLAG_STATUS_REG_CMD,
&flag_status_reg,
FLAG_STATUS_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles
needed for this
command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
return MT25QL_ERR_NONE;
}
/**
* \brief Execute a program command that crosses the page size boundary.
*
* \param[in] dev Pointer to MT25QL device structure
* \ref mt25ql_dev_t
* \param[in] opcode Opcode for the command.
* \param[in] write_data Pointer to a memory zone where the write_len
* number of bytes are located to write for this
* command.
* \param[in] write_len Number of bytes to write for the command.
* Between 1 and 8 bytes (both included) can be
* written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will execute two commands: one to program the bytes up to
* the page boundary and another one to program the rest. It will wait
* that bytes are programmed from first command before triggering the
* second one.
* \note This function does not send a write enable command before the first
* command and does not check that bytes were programmed after the second
* command.
*/
static enum mt25ql_error_t send_boundary_cross_write_cmd(
struct mt25ql_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
/*
* Remaining bytes between the current address and the end of the current
* page.
*/
uint32_t page_remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
/* First write up to the end of the current page. */
controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
opcode,
write_data,
page_remainder,
addr,
addr_bytes_number,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
write_data = (void *)((uint32_t)write_data + page_remainder);
addr += page_remainder;
/* Wait for the page to be written before sending new commands. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Then write the remaining data of the write_len bytes. */
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
opcode,
write_data,
write_len - page_remainder,
addr,
addr_bytes_number,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
enum mt25ql_functional_state_t config)
{
enum qspi_ip6514e_spi_mode_t spi_mode;
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
uint8_t opcode_read;
uint8_t opcode_write;
uint32_t dummy_cycles_read;
uint32_t dummy_cycles_write;
switch(config) {
case MT25QL_FUNC_STATE_DEFAULT:
spi_mode = QSPI_IP6514E_SPI_MODE;
opcode_read = READ_CMD;
dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES;
opcode_write = PAGE_PROGRAM_CMD;
dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_FAST:
spi_mode = QSPI_IP6514E_SPI_MODE;
opcode_read = FAST_READ_CMD;
dummy_cycles_read = FAST_READ_DUMMY_CYCLES;
opcode_write = PAGE_PROGRAM_CMD;
dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_QUAD_FAST:
spi_mode = QSPI_IP6514E_QSPI_MODE;
opcode_read = QUAD_OUTPUT_FAST_READ_CMD;
dummy_cycles_read = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD;
dummy_cycles_write = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
/* This function will first set the Flash memory SPI mode and then set
* the controller's SPI mode. It will fail if the two sides do not have
* the same mode when this function is called.
*/
library_error = set_spi_mode(dev, spi_mode);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Set the number of dummy cycles for read commands. */
library_error = change_dummy_cycles(dev, dummy_cycles_read);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* The rest of the configuration needs the controller to be disabled */
while(!qspi_ip6514e_is_idle(dev->controller));
qspi_ip6514e_disable(dev->controller);
/* Set the baud rate divisor as configured in the device structure. */
controller_error = qspi_ip6514e_set_baud_rate_div(dev->controller,
dev->baud_rate_div);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set opcode and dummy cycles needed for read commands. */
controller_error = qspi_ip6514e_cfg_reads(dev->controller,
opcode_read,
dummy_cycles_read);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set opcode and dummy cycles needed for write commands. */
controller_error = qspi_ip6514e_cfg_writes(dev->controller,
opcode_write,
dummy_cycles_write);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set Flash memory constants: bytes per page and address bytes. */
controller_error = qspi_ip6514e_cfg_page_size(dev->controller,
FLASH_PAGE_SIZE);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
controller_error = qspi_ip6514e_cfg_addr_bytes(dev->controller,
ADDR_BYTES);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
qspi_ip6514e_enable(dev->controller);
dev->func_state = config;
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev)
{
enum mt25ql_error_t library_error;
/*
* This function will first change the Flash memory mode to single SPI and
* then change the controller to single SPI. It will fail if the two sides
* do not have the same mode when this function is called.
*/
library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Set the default number of dummy cycles for read commands. */
library_error = change_dummy_cycles(dev, DEFAULT_READ_DUMMY_CYCLES);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* The rest of the configuration needs the controller to be disabled */
while(!qspi_ip6514e_is_idle(dev->controller));
qspi_ip6514e_disable(dev->controller);
/* Restore the default value of the QSPI controller registers. */
qspi_ip6514e_reset_regs(dev->controller);
qspi_ip6514e_enable(dev->controller);
dev->func_state = MT25QL_FUNC_STATE_DEFAULT;
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len)
{
/*
* The direct access window size is the size of the memory that can be
* accessed with a direct access.
*/
uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
/*
* The window number is the number of times it will be needed to remap the
* address with the remap register. We move this Direct Access window first
* window_number times starting at the beginning address to read full
* windows of direct_access_window_size bytes. Then we read the remainder
* bytes.
*/
uint32_t window_number = len / direct_access_window_size;
if (data == NULL || len == 0) {
return MT25QL_ERR_WRONG_ARGUMENT;
}
if ((addr + len) >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
/*
* There is no limitation reading through a Flash page boundary hence we
* do not add the same logic here than in the write function.
*/
/* Transfer the bytes for the window_number windows first. */
for (uint32_t window = 0; window < window_number; window++) {
qspi_ip6514e_remap_addr(dev->controller, addr);
/*
* The AHB address to access the Flash memory does not change but it
* will be translated differently thanks to the remap function.
*/
memcpy(data,
(void *)dev->direct_access_start_addr,
direct_access_window_size);
len -= direct_access_window_size;
data = (void *)((uint32_t)data + direct_access_window_size);
addr += direct_access_window_size;
}
if (len) {
/* Transfer the reminder bytes */
qspi_ip6514e_remap_addr(dev->controller, addr);
memcpy(data, (void *)dev->direct_access_start_addr, len);
}
/* Disable remapping for direct accesses outside of this function. */
qspi_ip6514e_disable_remap(dev->controller);
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len)
{
enum mt25ql_error_t library_error;
/*
* The direct access window size is the size of the memory that can be
* accessed with a direct access.
*/
uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
uint32_t window_number;
/* Offset between address and the previous 32 bits aligned word */
uint32_t word_offset;
if (data == NULL || len == 0) {
return MT25QL_ERR_WRONG_ARGUMENT;
}
if ((addr + len) >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
/*
* If the remapping address is not aligned on a 32 bits boundary, a direct
* access of one word could cross a Flash page boundary. If that happens,
* the bytes of that word that are over the page boundary will instead be
* written at the beginning of the same page.
* To counter this problem, we align the remapping address and add the word
* offset to the address of the direct access for the first window only.
*/
word_offset = addr % BYTES_PER_WORD;
/* Make address aligned on a 32 bits alignment. */
addr -= word_offset;
/*
* Only direct_access_window_size address locations are available by direct
* access. We calculate the number of windows that we will need to transfer
* len bytes. We have to add in the window the offset that we add in the
* beginning.
*/
window_number = (len + word_offset) / direct_access_window_size;
/*
* This function assumes that the flash has already been erased.
* Transfer the bytes for the window_number windows first.
*/
for (uint32_t window = 0; window < window_number; window++) {
/* The controller needs to be disabled while remapping is done. */
qspi_ip6514e_remap_addr(dev->controller, addr);
/*
* The AHB address to access the Flash memory does not change but it
* will be translated differently thanks to the remap function.
*/
memcpy((void *)(dev->direct_access_start_addr + word_offset),
data,
direct_access_window_size - word_offset);
len -= (direct_access_window_size - word_offset);
data = (void *)((uint32_t)data +
(direct_access_window_size - word_offset));
addr += direct_access_window_size;
/*
* The address is now aligned, there is no need to add an offset for the
* remaining windows.
*/
word_offset = 0;
/*
* Wait until the last program operation is complete before changing
* the remap address.
*/
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
if (len) {
/* Transfer the reminder bytes */
qspi_ip6514e_remap_addr(dev->controller, addr);
memcpy((void *)(dev->direct_access_start_addr + word_offset),
data,
len);
/* Wait until the last program operation is complete */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
/*
* Disable the default remap address for direct accesses outside of this
* function.
*/
qspi_ip6514e_disable_remap(dev->controller);
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len)
{
/* With one single command only 8 bytes can be read. */
uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
enum qspi_ip6514e_error_t controller_error;
uint8_t opcode;
uint32_t dummy_cycles;
switch (dev->func_state) {
case MT25QL_FUNC_STATE_QUAD_FAST:
opcode = QUAD_OUTPUT_FAST_READ_CMD;
dummy_cycles = QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_FAST:
opcode = FAST_READ_CMD;
dummy_cycles = FAST_READ_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_DEFAULT:
default:
opcode = READ_CMD;
dummy_cycles = DEFAULT_READ_DUMMY_CYCLES;
break;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
opcode,
data,
CMD_DATA_MAX_SIZE,
addr,
ADDR_BYTES,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
addr += CMD_DATA_MAX_SIZE;
len -= CMD_DATA_MAX_SIZE;
}
if (len) {
/* Read the remainder. */
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
opcode,
data,
len,
addr,
ADDR_BYTES,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len)
{
/* With one single command only 8 bytes can be written. */
uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
uint8_t opcode;
uint32_t dummy_cycles;
switch (dev->func_state) {
case MT25QL_FUNC_STATE_QUAD_FAST:
opcode = QUAD_INPUT_FAST_PROGRAM_CMD;
dummy_cycles = QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_FAST:
case MT25QL_FUNC_STATE_DEFAULT:
default:
opcode = PAGE_PROGRAM_CMD;
dummy_cycles = PAGE_PROGRAM_DUMMY_CYCLES;
break;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
send_write_enable(dev);
/*
* Check if this command is not writing over a page boundary: first and
* last bytes are in the same page.
*/
if ((addr / FLASH_PAGE_SIZE) !=
((addr + CMD_DATA_MAX_SIZE - 1) / FLASH_PAGE_SIZE)) {
/* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
library_error = send_boundary_cross_write_cmd(
dev,
opcode,
data,
CMD_DATA_MAX_SIZE,
addr,
ADDR_BYTES,
dummy_cycles);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
} else {
/* Normal case: not crossing the boundary. */
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
opcode,
data,
CMD_DATA_MAX_SIZE,
addr,
ADDR_BYTES,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
/* Wait until the write operation is complete. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
addr += CMD_DATA_MAX_SIZE;
len -= CMD_DATA_MAX_SIZE;
}
if (len) {
/* Write the remainder. */
send_write_enable(dev);
/*
* Check if this command is not writing over a page boundary: first and
* last bytes are in the same page.
*/
if ((addr / FLASH_PAGE_SIZE) != ((addr + len - 1) / FLASH_PAGE_SIZE)) {
/* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
library_error = send_boundary_cross_write_cmd(
dev,
opcode,
data,
len,
addr,
ADDR_BYTES,
dummy_cycles);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
} else {
/* Normal case: not crossing the boundary. */
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
opcode,
data,
len,
addr,
ADDR_BYTES,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
/* Wait until the write operation is complete. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
uint32_t addr,
enum mt25ql_erase_t erase_type)
{
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
uint8_t erase_cmd;
uint32_t addr_bytes;
send_write_enable(dev);
switch (erase_type) {
case MT25QL_ERASE_ALL_FLASH:
if (addr != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
erase_cmd = BULK_ERASE_CMD;
addr_bytes = ARG_NOT_USED;
break;
case MT25QL_ERASE_SECTOR_64K:
erase_cmd = SECTOR_ERASE_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SECTOR_64KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
case MT25QL_ERASE_SUBSECTOR_32K:
erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SUBSECTOR_32KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
case MT25QL_ERASE_SUBSECTOR_4K:
erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SUBSECTOR_4KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
if (addr >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
controller_error = qspi_ip6514e_send_cmd(dev->controller,
erase_cmd,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
addr,
addr_bytes,
0); /* No dummy cycles needed for
any erase command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Wait until the erase operation is complete */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}

View File

@ -1,252 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This library provides functions to control the MT25QL256ABA-1EW7-OSIT flash
* memory from Micron and should work for similar devices from the same vendor.
*/
#ifndef __MT25QL_H__
#define __MT25QL_H__
#include "qspi_ip6514e_drv.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MT25QL Flash Memory documentation defined values.
*/
#define FLASH_PAGE_SIZE (256U) /* 256B */
#define SUBSECTOR_4KB (0x00001000U) /* 4KB */
#define SUBSECTOR_32KB (0x00008000U) /* 32KB */
#define SECTOR_64KB (0x00010000U) /* 64KB */
#define ADDR_BYTES (3U)
enum mt25ql_error_t {
MT25QL_ERR_NONE = QSPI_IP6514E_ERR_NONE,
MT25QL_ERR_WRONG_ARGUMENT = QSPI_IP6514E_ERR_WRONG_ARGUMENT,
MT25QL_ERR_CTRL_NOT_DISABLED = QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
MT25QL_ERR_READ_IN_PROGRESS = QSPI_IP6514E_ERR_READ_IN_PROGRESS,
MT25QL_ERR_WRITE_IN_PROGRESS = QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
MT25QL_ERR_ADDR_NOT_ALIGNED,
MT25QL_ERR_ADDR_TOO_BIG,
};
enum mt25ql_erase_t {
MT25QL_ERASE_ALL_FLASH = 0U, /*!< Erase all flash */
MT25QL_ERASE_SUBSECTOR_4K = SUBSECTOR_4KB, /*!< Erase a 4 KB subsector */
MT25QL_ERASE_SUBSECTOR_32K = SUBSECTOR_32KB, /*!< Erase a 32 KB subsector */
MT25QL_ERASE_SECTOR_64K = SECTOR_64KB, /*!< Erase a sector (64 KB) */
};
enum mt25ql_functional_state_t {
MT25QL_FUNC_STATE_DEFAULT = 0U,
/*!< The QSPI Flash controller and memory is in default state,
* in the same state as after reset.
*/
MT25QL_FUNC_STATE_FAST = 1U,
/*!< The QSPI Flash controller and memory is configured to operate in
* single SPI mode and fast Flash commands could be used for read and
* program operations.
*/
MT25QL_FUNC_STATE_QUAD_FAST = 2U,
/*!< The QSPI Flash controller and memory is configured to operate in
* Quad SPI mode and fast Flash commands could be used for read and
* program operations.
*/
};
struct mt25ql_dev_t {
struct qspi_ip6514e_dev_t *controller;
/*!< QSPI Flash controller. */
uint32_t direct_access_start_addr;
/*!< AHB address to directly access the contents of the Flash memory
* through the QSPI Controller.
*/
uint32_t baud_rate_div;
/*!< Clock divisor that will be used to configure the QSPI Flash
* Controller to access the Flash memory. The clock which frequency is
* divived is the one linked to the QSPI Flash controller. It can only
* be an even number between 2 and 32 (both included). It needs to be
* high enough to support the Quad Output Fast Read command with 8
* dummy cycles and the Quad Input Fast Program with 0 dummy cycles.
*/
uint32_t size; /*!< Total size of the MT25QL Flash memory */
enum mt25ql_functional_state_t func_state;
/*!< Functional state (operational parameter settings) of the
* QSPI Flash controller and memory.
*/
};
/**
* \brief Change configuration of the QSPI Flash controller and MT25QL memory
*
* Changes the configuration of the QSPI Flash controller and MT25QL
* Flash memory to operate in the specified SPI mode and to use the
* appropriate Flash commands for read and program operations.
* It also sets:
* + The number of dummy cycles for each operation
* + The bytes per page constant to 256 (MT25QL Flash specific)
* + The number of address bytes to 3
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] config Operational configuration to be set on flash controller
* and device \ref mt25ql_functional_state_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function assumes that the Flash memory device and the QSPI Flash
* controller operates with the same SPI protocol. This function will fail
* if the Flash device is in a different configuration.
*/
enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
enum mt25ql_functional_state_t config);
/**
* \brief Restore the QSPI Flash controller and MT25QL to default state.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function assumes that the Flash memory device and the QSPI Flash
* controller operates with the same SPI protocol. This function will fail
* if the Flash device is in a different configuration.
*/
enum mt25ql_error_t mt25ql_restore_default_state(struct mt25ql_dev_t* dev);
/**
* \brief Read bytes from the flash memory (direct access)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the read operation
* \param[out] data Pointer where len bytes read from the flash memory will be
* written to
* \param[in] len Number of bytes to read
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use direct access to read from the Flash memory. It
* can be used to access above the direct accessible memory zone if
* not all the AHB address wires are connected.
* \note The address given should be the address of the data inside the flash
* memory. To read the first byte inside the memory, use 0x00000000.
*/
enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len);
/**
* \brief Write bytes in the flash memory, at a location where data has already
* been erased (direct access)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the write operation
* \param[in] data Pointer to the len bytes that will be written to the flash
* memory
* \param[in] len Number of bytes to write
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use direct access to write to the Flash memory. It
* can be used to access outside of the direct accessible memory zone if
* not all the AHB address wires are connected.
* \note The address given should be the address of the data inside the flash
* memory. To write the first byte inside the memory, use 0x00000000.
* \note Writing bytes in the flash memory clear them from 1 to 0, for that
* matter the location where data is written needs to be erased
* beforehand.
*/
enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len);
/**
* \brief Read bytes from the flash memory (using Flash commands)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the read operation
* \param[out] data Pointer where len bytes read from the flash memory will be
* written to
* \param[in] len Number of bytes to read
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use the Software Triggered Instruction Generator to
* read from the Flash memory using Flash commands.
* \note The address given should be the address of the data inside the flash
* memory. To read the first byte inside the memory, use 0x00000000.
*/
enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len);
/**
* \brief Write bytes in the flash memory, at a location where data has already
* been erased (using Flash commands)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the write operation
* \param[in] data Pointer to the len bytes that will be written to the flash
* memory
* \param[in] len Number of bytes to write
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use the Software Triggered Instruction Generator to
* write to the Flash memory using Flash commands.
* \note The address given should be the address of the data inside the flash
* memory. To write the first byte inside the memory, use 0x00000000.
* \note Writing bytes in the flash memory clear them from 1 to 0, for that
* matter the location where data is written needs to be erased
* beforehand.
*/
enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len);
/**
* \brief Erase all flash memory, a sector (64 KiB) or a subsector
* (32 KiB or 4 KiB)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Address where to erase in the flash memory
* \param[in] erase_type Type of what to erase at the specified address:
* * whole flash memory
* * a subsector (4 KiB or 32 KiB)
* * a sector (64 KiB)
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note The address need to be aligned with the size of what is erased or 0 if
* all flash memory is to be erased.
*/
enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
uint32_t addr,
enum mt25ql_erase_t erase_type);
#ifdef __cplusplus
}
#endif
#endif /* __MT25QL_H__ */

View File

@ -1,153 +0,0 @@
#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
/*
* Copyright (c) 2018-2019 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../../../partition/region_defs.h"
#if !defined(TFM_LVL)
#define TFM_LVL 1
#endif
#if !defined(MBED_ROM_START)
#define MBED_ROM_START S_CODE_START // 0x10020400
#endif
#if !defined(MBED_ROM_SIZE)
#define MBED_ROM_SIZE IMAGE_CODE_SIZE // 0x7f800
#endif
#if !defined(MBED_RAM_START)
#define MBED_RAM_START S_DATA_START // 0x30000000
#endif
#if !defined(MBED_RAM_SIZE)
#define MBED_RAM_SIZE S_DATA_SIZE // 0x11000
#endif
LR_CODE MBED_ROM_START MBED_ROM_SIZE {
/**** This initial section contains common code for TEE */
ER_TFM_CODE MBED_ROM_START S_CODE_SIZE {
*.o (RESET +First)
.ANY (+RO)
}
#if TFM_LVL == 1
/* Shared area between BL2 and runtime to exchange data */
TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
}
/* MSP */
ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE {
}
/* PSP */
ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE {
}
ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE {
}
ER_TFM_DATA +0 {
.ANY (+RW +ZI)
}
TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x1000 {
}
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
#else /* TFM_LVL == 1 */
/**** Unprivileged Secure code start here */
TFM_UNPRIV_CODE +0 ALIGN 32 {
tfm_spm_services.o (+RO)
platform_retarget_dev.o (+RO)
*(SFN)
*armlib*
}
TFM_SP_PLATFORM +0 ALIGN 32 {
*tfm_platform* (+RO)
*(TFM_SP_PLATFORM_ATTR_FN)
}
/* Shared area between BL2 and runtime to exchange data */
TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
}
/* MSP */
ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE {
}
/* PSP */
ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE {
}
ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE {
}
ER_TFM_DATA +0 {
.ANY (+RW +ZI)
}
TFM_UNPRIV_RO_DATA +0 ALIGN 32 {
tfm_spm_services.o (+RW +ZI)
platform_retarget_dev.o (+RW +ZI)
}
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
TFM_SP_PLATFORM_DATA +0 ALIGN 32 {
*tfm_platform* (+RW +ZI)
}
TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
}
#endif /* TFM_LVL == 1 */
/* This empty, zero long execution region is here to mark the limit address
* of the last execution region that is allocated in SRAM.
*/
SRAM_WATERMARK +0 EMPTY 0x0 {
}
ER_CODE_CMSE_VENEER CMSE_VENEER_REGION_START FIXED PADVALUE 0xFFFFFFFF CMSE_VENEER_REGION_SIZE {
*(Veneer$$CMSE)
}
/* Make sure that the sections allocated in the SRAM does not exceed the
* size of the SRAM available.
*/
ScatterAssert(ImageLimit(SRAM_WATERMARK) <= MBED_RAM_START + MBED_RAM_SIZE)
}
LR_NS_PARTITION NS_PARTITION_START {
/* Reserved place for NS application.
* No code will be placed here, just address of this region is used in the
* secure code to configure certain HW components.
*/
ER_NS_PARTITION NS_PARTITION_START EMPTY NS_PARTITION_SIZE {
}
}

View File

@ -1,254 +0,0 @@
;/*
; * Copyright (c) 2017-2019 ARM Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; */
;
; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s
; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
;/*
;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
;*/
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
IMPORT |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit|
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors ;Core Interrupts
DCD |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit| ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD SecureFault_Handler ; Secure Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
;SSE-200 Interrupts
DCD NS_WATCHDOG_RESET_IRQHandler ; 0: Non-Secure Watchdog Reset Request Interrupt
DCD NS_WATCHDOG_IRQHandler ; 1: Non-Secure Watchdog Interrupt
DCD S32K_TIMER_IRQHandler ; 2: S32K Timer Interrupt
DCD TIMER0_IRQHandler ; 3: CMSDK Timer 0 Interrupt
DCD TIMER1_IRQHandler ; 4: CMSDK Timer 1 Interrupt
DCD DUALTIMER_IRQHandler ; 5: CMSDK Dual Timer Interrupt
DCD MHU0_IRQHandler ; 6: Message Handling Unit 0 Interrupt
DCD MHU1_IRQHandler ; 7: Message Handling Unit 1 Interrupt
DCD CRYPTOCELL_IRQHandler ; 8: CryptoCell-312 Interrupt
DCD MPC_Handler ; 9: Secure Combined MPC Interrupt
DCD PPC_Handler ; 10: Secure Combined PPC Interrupt
DCD S_MSC_COMBINED_IRQHandler ; 11: Secure Combined MSC Interrupt
DCD S_BRIDGE_ERR_IRQHandler ; 12: Secure Bridge Error Combined Interrupt
DCD I_CACHE_INV_ERR_IRQHandler ; 13: Intsruction Cache Invalidation Interrupt
DCD 0 ; 14: Reserved
DCD SYS_PPU_IRQHandler ; 15: System PPU Interrupt
DCD CPU0_PPU_IRQHandler ; 16: CPU0 PPU Interrupt
DCD CPU1_PPU_IRQHandler ; 17: CPU1 PPU Interrupt
DCD CPU0_DGB_PPU_IRQHandler ; 18: CPU0 Debug PPU Interrupt
DCD CPU1_DGB_PPU_IRQHandler ; 19: CPU1 Debug PPU Interrupt
DCD CRYPTOCELL_PPU_IRQHandler ; 20: CryptoCell PPU Interrupt
DCD 0 ; 21: Reserved
DCD RAM0_PPU_IRQHandler ; 22: RAM 0 PPU Interrupt
DCD RAM1_PPU_IRQHandler ; 23: RAM 1 PPU Interrupt
DCD RAM2_PPU_IRQHandler ; 24: RAM 2 PPU Interrupt
DCD RAM3_PPU_IRQHandler ; 25: RAM 3 PPU Interrupt
DCD DEBUG_PPU_IRQHandler ; 26: Debug PPU Interrupt
DCD 0 ; 27: Reserved
DCD CPU0_CTI_IRQHandler ; 28: CPU0 CTI Interrupt
DCD CPU1_CTI_IRQHandler ; 29: CPU1 CTI Interrupt
DCD 0 ; 30: Reserved
DCD 0 ; 31: Reserved
;Expansion Interrupts
DCD 0 ; 32: Reserved
DCD GpTimer_IRQHandler ; 33: General Purpose Timer
DCD I2C0_IRQHandler ; 34: I2C0
DCD I2C1_IRQHandler ; 35: I2C1
DCD I2S_IRQHandler ; 36: I2S
DCD SPI_IRQHandler ; 37: SPI
DCD QSPI_IRQHandler ; 38: QSPI
DCD UARTRX0_Handler ; 39: UART0 receive FIFO interrupt
DCD UARTTX0_Handler ; 40: UART0 transmit FIFO interrupt
DCD UART0_RxTimeout_IRQHandler ; 41: UART0 receive timeout interrupt
DCD UART0_ModemStatus_IRQHandler ; 42: UART0 modem status interrupt
DCD UART0_Error_IRQHandler ; 43: UART0 error interrupt
DCD UART0_IRQHandler ; 44: UART0 interrupt
DCD UARTRX1_Handler ; 45: UART0 receive FIFO interrupt
DCD UARTTX1_Handler ; 46: UART0 transmit FIFO interrupt
DCD UART1_RxTimeout_IRQHandler ; 47: UART0 receive timeout interrupt
DCD UART1_ModemStatus_IRQHandler ; 48: UART0 modem status interrupt
DCD UART1_Error_IRQHandler ; 49: UART0 error interrupt
DCD UART1_IRQHandler ; 50: UART0 interrupt
DCD GPIO_0_IRQHandler ; 51: GPIO 0 interrupt
DCD GPIO_1_IRQHandler ; 52: GPIO 1 interrupt
DCD GPIO_2_IRQHandler ; 53: GPIO 2 interrupt
DCD GPIO_3_IRQHandler ; 54: GPIO 3 interrupt
DCD GPIO_4_IRQHandler ; 55: GPIO 4 interrupt
DCD GPIO_5_IRQHandler ; 56: GPIO 5 interrupt
DCD GPIO_6_IRQHandler ; 57: GPIO 6 interrupt
DCD GPIO_7_IRQHandler ; 58: GPIO 7 interrupt
DCD GPIO_8_IRQHandler ; 59: GPIO 8 interrupt
DCD GPIO_9_IRQHandler ; 60: GPIO 9 interrupt
DCD GPIO_10_IRQHandler ; 61: GPIO 10 interrupt
DCD GPIO_11_IRQHandler ; 62: GPIO 11 interrupt
DCD GPIO_12_IRQHandler ; 63: GPIO 12 interrupt
DCD GPIO_13_IRQHandler ; 64: GPIO 13 interrupt
DCD GPIO_14_IRQHandler ; 65: GPIO 14 interrupt
DCD GPIO_15_IRQHandler ; 66: GPIO 15 interrupt
DCD Combined_IRQHandler ; 67: Combined interrupt
DCD PVT_IRQHandler ; 68: PVT sensor interrupt
DCD 0 ; 69: Reserved
DCD PWM_0_IRQHandler ; 70: PWM0 interrupt
DCD RTC_IRQHandler ; 71: RTC interrupt
DCD GpTimer0_IRQHandler ; 72: General Purpose Timer0
DCD GpTimer1_IRQHandler ; 73: General Purpose Timer1
DCD PWM_1_IRQHandler ; 74: PWM1 interrupt
DCD PWM_2_IRQHandler ; 75: PWM2 interrupt
DCD IOMUX_IRQHandler ; 76: IOMUX interrupt
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
; Reset Handler
AREA |.text|, CODE, READONLY
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
CPSID i ; Disable IRQs
LDR R0, =SystemInit
BLX R0
MRS R0, control ; Get control value
ORR R0, R0, #2 ; Select switch to PSP
MSR control, R0
LDR R0, =__main
BX R0
ENDP
End_Of_Main
B .
; Dummy Exception Handlers (infinite loops which can be modified)
MACRO
Default_Handler $handler_name
$handler_name PROC
EXPORT $handler_name [WEAK]
B .
ENDP
MEND
Default_Handler NMI_Handler
Default_Handler HardFault_Handler
Default_Handler MemManage_Handler
Default_Handler BusFault_Handler
Default_Handler UsageFault_Handler
Default_Handler SecureFault_Handler
Default_Handler SVC_Handler
Default_Handler DebugMon_Handler
Default_Handler PendSV_Handler
Default_Handler SysTick_Handler
Default_Handler NS_WATCHDOG_RESET_IRQHandler
Default_Handler NS_WATCHDOG_IRQHandler
Default_Handler S32K_TIMER_IRQHandler
Default_Handler TIMER0_IRQHandler
Default_Handler TIMER1_IRQHandler
Default_Handler DUALTIMER_IRQHandler
Default_Handler MHU0_IRQHandler
Default_Handler MHU1_IRQHandler
Default_Handler CRYPTOCELL_IRQHandler
Default_Handler MPC_Handler
Default_Handler PPC_Handler
Default_Handler S_MSC_COMBINED_IRQHandler
Default_Handler S_BRIDGE_ERR_IRQHandler
Default_Handler I_CACHE_INV_ERR_IRQHandler
Default_Handler SYS_PPU_IRQHandler
Default_Handler CPU0_PPU_IRQHandler
Default_Handler CPU1_PPU_IRQHandler
Default_Handler CPU0_DGB_PPU_IRQHandler
Default_Handler CPU1_DGB_PPU_IRQHandler
Default_Handler CRYPTOCELL_PPU_IRQHandler
Default_Handler RAM0_PPU_IRQHandler
Default_Handler RAM1_PPU_IRQHandler
Default_Handler RAM2_PPU_IRQHandler
Default_Handler RAM3_PPU_IRQHandler
Default_Handler DEBUG_PPU_IRQHandler
Default_Handler CPU0_CTI_IRQHandler
Default_Handler CPU1_CTI_IRQHandler
Default_Handler GpTimer_IRQHandler
Default_Handler I2C0_IRQHandler
Default_Handler I2C1_IRQHandler
Default_Handler I2S_IRQHandler
Default_Handler SPI_IRQHandler
Default_Handler QSPI_IRQHandler
Default_Handler UARTRX0_Handler
Default_Handler UARTTX0_Handler
Default_Handler UART0_RxTimeout_IRQHandler
Default_Handler UART0_ModemStatus_IRQHandler
Default_Handler UART0_Error_IRQHandler
Default_Handler UART0_IRQHandler
Default_Handler UARTRX1_Handler
Default_Handler UARTTX1_Handler
Default_Handler UART1_RxTimeout_IRQHandler
Default_Handler UART1_ModemStatus_IRQHandler
Default_Handler UART1_Error_IRQHandler
Default_Handler UART1_IRQHandler
Default_Handler GPIO_0_IRQHandler
Default_Handler GPIO_1_IRQHandler
Default_Handler GPIO_2_IRQHandler
Default_Handler GPIO_3_IRQHandler
Default_Handler GPIO_4_IRQHandler
Default_Handler GPIO_5_IRQHandler
Default_Handler GPIO_6_IRQHandler
Default_Handler GPIO_7_IRQHandler
Default_Handler GPIO_8_IRQHandler
Default_Handler GPIO_9_IRQHandler
Default_Handler GPIO_10_IRQHandler
Default_Handler GPIO_11_IRQHandler
Default_Handler GPIO_12_IRQHandler
Default_Handler GPIO_13_IRQHandler
Default_Handler GPIO_14_IRQHandler
Default_Handler GPIO_15_IRQHandler
Default_Handler Combined_IRQHandler
Default_Handler PVT_IRQHandler
Default_Handler PWM_0_IRQHandler
Default_Handler RTC_IRQHandler
Default_Handler GpTimer0_IRQHandler
Default_Handler GpTimer1_IRQHandler
Default_Handler PWM_1_IRQHandler
Default_Handler PWM_2_IRQHandler
Default_Handler IOMUX_IRQHandler
ALIGN
END

View File

@ -1,366 +0,0 @@
;/*
; * Copyright (c) 2018-2019 ARM Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; *
; * This file is derivative of CMSIS V5.00 gcc_arm.ld
; */
/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
/* Linker script to configure memory regions. */
/* This file will be run trough the pre-processor. */
#include "../../../partition/region_defs.h"
#if !defined(TFM_LVL)
#define TFM_LVL 1
#endif
MEMORY
{
FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
RAM (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
VENEERS (rx) : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE
}
HEAP_SIZE = S_HEAP_SIZE;
__heap_size__ = S_HEAP_SIZE;
__psp_stack_size__ = S_PSP_STACK_SIZE;
__msp_init_stack_size__ = S_MSP_STACK_SIZE;
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a libc_nano.a)
ENTRY(Reset_Handler)
SECTIONS
{
.TFM_VECTORS : ALIGN(4)
{
__vectors_start__ = .;
KEEP(*(.vectors))
*startup*(.text*)
. = ALIGN(4);
__vectors_end__ = .;
} > FLASH
#if TFM_LVL == 1
.copy.table : ALIGN(4)
{
__copy_table_start__ = .;
LONG (LOADADDR(.TFM_DATA))
LONG (ADDR(.TFM_DATA))
LONG (SIZEOF(.TFM_DATA))
__copy_table_end__ = .;
} > FLASH
.zero.table : ALIGN(4)
{
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
LONG (ADDR(.TFM_SECURE_STACK))
LONG (SIZEOF(.TFM_SECURE_STACK))
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
} > FLASH
#else /* TFM_LVL == 1 */
.copy.table : ALIGN(4)
{
__copy_table_start__ = .;
LONG (LOADADDR(.TFM_DATA))
LONG (ADDR(.TFM_DATA))
LONG (SIZEOF(.TFM_DATA))
LONG (LOADADDR(.TFM_UNPRIV_RO_DATA))
LONG (ADDR(.TFM_UNPRIV_RO_DATA))
LONG (SIZEOF(.TFM_UNPRIV_RO_DATA))
LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
LONG (ADDR(.TFM_SP_PLATFORM_DATA))
LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
__copy_table_end__ = .;
} > FLASH
.zero.table : ALIGN(4)
{
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
LONG (ADDR(.TFM_UNPRIV_RO_BSS))
LONG (SIZEOF(.TFM_UNPRIV_RO_BSS))
LONG (ADDR(.TFM_SP_PLATFORM_BSS))
LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
LONG (ADDR(.TFM_SP_PLATFORM_STACK))
LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
} > FLASH
.TFM_UNPRIV_CODE : ALIGN(32)
{
*libc_nano*:*(.text*)
*libc_nano*:*(.rodata*)
*tfm_spm_services.o(.text*)
*tfm_spm_services.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
*libgcc*:*(.text*)
*libgcc*:*(.rodata*)
. = ALIGN(32);
} > FLASH
Image$$TFM_UNPRIV_CODE$$RO$$Base = ADDR(.TFM_UNPRIV_CODE);
Image$$TFM_UNPRIV_CODE$$RO$$Limit = ADDR(.TFM_UNPRIV_CODE) + SIZEOF(.TFM_UNPRIV_CODE);
.TFM_SP_PLATFORM : ALIGN(32)
{
*tfm_platform*:*(.text*)
*tfm_platform*:*(.rodata*)
*(TFM_SP_PLATFORM_ATTR_FN)
. = ALIGN(32);
} > FLASH
Image$$TFM_SP_PLATFORM$$RO$$Base = ADDR(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$RO$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
#endif /* TFM_LVL == 1 */
.ER_TFM_CODE :
{
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
OVERLAY S_DATA_START :
{
/* shared_data and msp_stack are overlapping on purpose when
* msp_stack is extended until the beginning of RAM, when shared_date
* was read out by partitions
*/
.tfm_bl2_shared_data
{
. = ALIGN(32);
. += BOOT_TFM_SHARED_DATA_SIZE;
}
.msp_stack
{
. = ALIGN(32);
. += S_MSP_STACK_SIZE;
}
} > RAM
Image$$ARM_LIB_STACK_MSP$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
.psp_stack :
{
. = ALIGN(32);
. += S_PSP_STACK_SIZE;
} > RAM
Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.psp_stack);
Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.psp_stack) + SIZEOF(.psp_stack);
#if TFM_LVL == 1
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += S_HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > RAM
Image$$ARM_LIB_HEAP$$ZI$$Base = ADDR(.heap);
Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
.TFM_SECURE_STACK :
{
. = ALIGN(128);
. += 0x1000;
} > RAM
Image$$TFM_SECURE_STACK$$ZI$$Base = ADDR(.TFM_SECURE_STACK);
Image$$TFM_SECURE_STACK$$ZI$$Limit = ADDR(.TFM_SECURE_STACK) + SIZEOF(.TFM_SECURE_STACK);
.TFM_UNPRIV_SCRATCH :
{
. = ALIGN(32);
. += 0x400;
} > RAM
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
#else /* TFM_LVL == 1 */
.TFM_UNPRIV_RO_DATA :
{
*/tfm_spm_services.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$RW$$Base = ADDR(.TFM_UNPRIV_RO_DATA);
Image$$TFM_UNPRIV_RO_DATA$$RW$$Limit = ADDR(.TFM_UNPRIV_RO_DATA) + SIZEOF(.TFM_UNPRIV_RO_DATA);
.TFM_UNPRIV_RO_BSS : ALIGN(32)
{
*/tfm_spm_services.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/tfm_spm_services.o(COMMON)
*/platform_retarget_dev.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Limit = ADDR(.TFM_UNPRIV_RO_BSS) + SIZEOF(.TFM_UNPRIV_RO_BSS);
.TFM_UNPRIV_SCRATCH : ALIGN(32)
{
. += 0x400;
} > RAM AT> FLASH
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
.TFM_SP_PLATFORM_DATA : ALIGN(32)
{
*tfm_platform*:*(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_DATA$$RW$$Base = ADDR(.TFM_SP_PLATFORM_DATA);
Image$$TFM_SP_PLATFORM_DATA$$RW$$Limit = ADDR(.TFM_SP_PLATFORM_DATA) + SIZEOF(.TFM_SP_PLATFORM_DATA);
.TFM_SP_PLATFORM_BSS : ALIGN(32)
{
*tfm_platform*:*(.bss*)
*tfm_platform*:*(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_BSS);
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_BSS) + SIZEOF(.TFM_SP_PLATFORM_BSS);
.TFM_SP_PLATFORM_STACK : ALIGN(128)
{
. += 0x0400;
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
#endif /* TFM_LVL == 1 */
.TFM_DATA :
{
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
} > RAM AT> FLASH
Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
ASSERT(Image$$ER_TFM_DATA$$Limit <= S_DATA_START + S_DATA_SIZE, "Exceeding secure RAM")
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
* separate 32 bytes aligned region so that the SAU can programmed to just set
* this region as Non-Secure Callable.
*/
.gnu.sgstubs : ALIGN(32)
{
*(.gnu.sgstubs*)
. = ALIGN(32);
} > VENEERS AT> VENEERS
Image$$ER_CODE_CMSE_VENEER$$Base = ADDR(.gnu.sgstubs);
Image$$ER_CODE_CMSE_VENEER$$Limit = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs);
Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
PROVIDE(__StackTop = __stack);
PROVIDE(__StackLimit = __StackTop - SIZEOF(.psp_stack));
}

View File

@ -1,365 +0,0 @@
;/*
; * Copyright (c) 2009-2019 ARM Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; *
; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S
; */
.syntax unified
.arch armv8-m.main
.section .vectors
.align 2
.globl __Vectors
__Vectors:
.long Image$$ARM_LIB_STACK_MSP$$ZI$$Limit /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long MemManage_Handler /* MPU Fault Handler */
.long BusFault_Handler /* Bus Fault Handler */
.long UsageFault_Handler /* Usage Fault Handler */
.long SecureFault_Handler /* Secure Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long DebugMon_Handler /* Debug Monitor Handler */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* Core interrupts */
.long NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */
.long NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */
.long S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */
.long TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */
.long TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */
.long DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */
.long MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */
.long MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */
.long CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */
.long MPC_Handler /* 9: Secure Combined MPC Interrupt */
.long PPC_Handler /* 10: Secure Combined PPC Interrupt */
.long S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */
.long S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */
.long I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */
.long 0 /* 14: Reserved */
.long SYS_PPU_IRQHandler /* 15: System PPU Interrupt */
.long CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */
.long CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */
.long CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */
.long CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */
.long CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */
.long 0 /* 21: Reserved */
.long RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */
.long RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */
.long RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */
.long RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */
.long DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */
.long 0 /* 27: Reserved */
.long CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */
.long CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */
.long 0 /* 30: Reserved */
.long 0 /* 31: Reserved */
/* External interrupts */
.long 0 /* 32: Reserved */
.long GpTimer_IRQHandler /* 33: General Purpose Timer */
.long I2C0_IRQHandler /* 34: I2C0 */
.long I2C1_IRQHandler /* 35: I2C1 */
.long I2S_IRQHandler /* 36: I2S */
.long SPI_IRQHandler /* 37: SPI */
.long QSPI_IRQHandler /* 38: QSPI */
.long UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */
.long UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */
.long UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */
.long UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */
.long UART0_Error_IRQHandler /* 43: UART0 error interrupt */
.long UART0_IRQHandler /* 44: UART0 interrupt */
.long UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */
.long UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */
.long UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */
.long UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */
.long UART1_Error_IRQHandler /* 49: UART0 error interrupt */
.long UART1_IRQHandler /* 50: UART0 interrupt */
.long GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */
.long GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */
.long GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */
.long GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */
.long GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */
.long GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */
.long GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */
.long GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */
.long GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */
.long GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */
.long GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */
.long GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */
.long GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */
.long GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */
.long GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */
.long GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */
.long Combined_IRQHandler /* 67: Combined interrupt */
.long PVT_IRQHandler /* 68: PVT sensor interrupt */
.long 0 /* 69: Reserved */
.long PWM_0_IRQHandler /* 70: PWM0 interrupt */
.long RTC_IRQHandler /* 71: RTC interrupt */
.long GpTimer0_IRQHandler /* 72: General Purpose Timer0 */
.long GpTimer1_IRQHandler /* 73: General Purpose Timer1 */
.long PWM_1_IRQHandler /* 74: PWM1 interrupt */
.long PWM_2_IRQHandler /* 75: PWM2 interrupt */
.long IOMUX_IRQHandler /* 76: IOMUX interrupt */
.size __Vectors, . - __Vectors
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Firstly it copies data from read only memory to RAM. There are two schemes
* to copy. One can copy more than one sections. Another can only copy
* one section. The former scheme needs more instructions and read-only
* data to implement than the latter.
* Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
#ifdef __STARTUP_COPY_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of triplets, each of which specify:
* offset 0: LMA of start of a section to copy from
* offset 4: VMA of start of a section to copy to
* offset 8: size of the section to copy. Must be multiply of 4
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r4, =__copy_table_start__
ldr r5, =__copy_table_end__
.L_loop0:
cmp r4, r5
bge .L_loop0_done
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]
.L_loop0_0:
subs r3, #4
ittt ge
ldrge r0, [r1, r3]
strge r0, [r2, r3]
bge .L_loop0_0
adds r4, #12
b .L_loop0
.L_loop0_done:
#else
/* Single section scheme.
*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
.L_loop1:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .L_loop1
#endif /*__STARTUP_COPY_MULTIPLE */
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* There are two schemes too. One can clear multiple BSS sections. Another
* can only clear one section. The former is more size expensive than the
* latter.
*
* Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
* Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
*/
#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of tuples specifying:
* offset 0: Start of a BSS section
* offset 4: Size of this BSS section. Must be multiply of 4
*/
ldr r3, =__zero_table_start__
ldr r4, =__zero_table_end__
.L_loop2:
cmp r3, r4
bge .L_loop2_done
ldr r1, [r3]
ldr r2, [r3, #4]
movs r0, 0
.L_loop2_0:
subs r2, #4
itt ge
strge r0, [r1, r2]
bge .L_loop2_0
adds r3, #8
b .L_loop2
.L_loop2_done:
#elif defined (__STARTUP_CLEAR_BSS)
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.L_loop3:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .L_loop3
#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
cpsid i /* Disable IRQs */
bl SystemInit
mrs r0, control /* Get control value */
orr r0, r0, #2 /* Select switch to PSP */
msr control, r0
ldr r0, =Image$$ARM_LIB_STACK$$ZI$$Limit
msr psp, r0
#ifndef __START
#define __START _start
#endif
bl __START
.pool
.size Reset_Handler, . - Reset_Handler
/* Macro to define default handlers. */
.macro def_irq_handler handler_name
.align 1
.thumb_func
.weak \handler_name
\handler_name:
b \handler_name
.endm
def_irq_handler NMI_Handler
def_irq_handler HardFault_Handler
def_irq_handler MemManage_Handler
def_irq_handler BusFault_Handler
def_irq_handler UsageFault_Handler
def_irq_handler SecureFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
/* Core interrupts */
def_irq_handler NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */
def_irq_handler NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */
def_irq_handler S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */
def_irq_handler TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */
def_irq_handler TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */
def_irq_handler DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */
def_irq_handler MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */
def_irq_handler MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */
def_irq_handler CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */
def_irq_handler MPC_Handler /* 9: Secure Combined MPC Interrupt */
def_irq_handler PPC_Handler /* 10: Secure Combined PPC Interrupt */
def_irq_handler S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */
def_irq_handler S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */
def_irq_handler I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */
def_irq_handler SYS_PPU_IRQHandler /* 15: System PPU Interrupt */
def_irq_handler CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */
def_irq_handler CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */
def_irq_handler CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */
def_irq_handler CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */
def_irq_handler CRYPTOCELL_PPU_IRQHandler /* 20: CryptoCell PPU Interrupt */
def_irq_handler RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */
def_irq_handler RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */
def_irq_handler RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */
def_irq_handler RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */
def_irq_handler DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */
def_irq_handler CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */
def_irq_handler CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */
/* External interrupts */
def_irq_handler GpTimer_IRQHandler /* 33: General Purpose Timer */
def_irq_handler I2C0_IRQHandler /* 34: I2C0 */
def_irq_handler I2C1_IRQHandler /* 35: I2C1 */
def_irq_handler I2S_IRQHandler /* 36: I2S */
def_irq_handler SPI_IRQHandler /* 37: SPI */
def_irq_handler QSPI_IRQHandler /* 38: QSPI */
def_irq_handler UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */
def_irq_handler UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */
def_irq_handler UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */
def_irq_handler UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */
def_irq_handler UART0_Error_IRQHandler /* 43: UART0 error interrupt */
def_irq_handler UART0_IRQHandler /* 44: UART0 interrupt */
def_irq_handler UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */
def_irq_handler UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */
def_irq_handler UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */
def_irq_handler UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */
def_irq_handler UART1_Error_IRQHandler /* 49: UART0 error interrupt */
def_irq_handler UART1_IRQHandler /* 50: UART0 interrupt */
def_irq_handler GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */
def_irq_handler GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */
def_irq_handler GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */
def_irq_handler GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */
def_irq_handler GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */
def_irq_handler GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */
def_irq_handler GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */
def_irq_handler GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */
def_irq_handler GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */
def_irq_handler GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */
def_irq_handler GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */
def_irq_handler GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */
def_irq_handler GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */
def_irq_handler GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */
def_irq_handler GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */
def_irq_handler GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */
def_irq_handler Combined_IRQHandler /* 67: Combined interrupt */
def_irq_handler PVT_IRQHandler /* 68: PVT sensor interrupt */
def_irq_handler PWM_0_IRQHandler /* 70: PWM0 interrupt */
def_irq_handler RTC_IRQHandler /* 71: RTC interrupt */
def_irq_handler GpTimer0_IRQHandler /* 72: General Purpose Timer0 */
def_irq_handler GpTimer1_IRQHandler /* 73: General Purpose Timer1 */
def_irq_handler PWM_1_IRQHandler /* 74: PWM1 interrupt */
def_irq_handler PWM_2_IRQHandler /* 75: PWM2 interrupt */
def_irq_handler IOMUX_IRQHandler /* 76: IOMUX interrupt */
.end

View File

@ -1,652 +0,0 @@
/*
* Copyright (c) 2016-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mpc_sie200_drv.h"
#include <stddef.h>
#include "cmsis.h"
#define MPC_SIE200_BLK_CFG_OFFSET 5U
#define MPC_SIE200_CTRL_SEC_RESP (1UL << 4UL) /* MPC fault triggers a
* bus error */
#define MPC_SIE200_CTRL_AUTOINCREMENT (1UL << 8UL) /* BLK_IDX auto increment */
#define MPC_SIE200_CTRL_SEC_LOCK_DOWN (1UL << 31UL) /* MPC Security lock down */
/* ARM MPC interrupt */
#define MPC_SIE200_INT_EN 1UL
#define MPC_SIE200_INT_STAT 1UL
/* ARM MPC state definitions */
#define MPC_SIE200_INITIALIZED (1 << 0)
/* Error code returned by the internal driver functions */
enum mpc_sie200_intern_error_t{
MPC_SIE200_INTERN_ERR_NONE = MPC_SIE200_ERR_NONE,
MPC_SIE200_INTERN_ERR_NOT_IN_RANGE = MPC_SIE200_ERR_NOT_IN_RANGE,
MPC_SIE200_INTERN_ERR_NOT_ALIGNED = MPC_SIE200_ERR_NOT_ALIGNED,
MPC_SIE200_INTERN_ERR_INVALID_RANGE = MPC_SIE200_ERR_INVALID_RANGE,
MPC_INTERN_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE =
MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE,
/* Calculated block index
is higher than the maximum allowed by the MPC. It should never
happen unless the controlled ranges of the MPC are misconfigured
in the driver or if the IP has not enough LUTs to cover the
range, due to wrong reported block size for example.
*/
MPC_SIE200_INTERN_ERR_BLK_IDX_TOO_HIGH = -1,
};
/* ARM MPC memory mapped register access structure */
struct mpc_sie200_reg_map_t {
volatile uint32_t ctrl; /* (R/W) MPC Control */
volatile uint32_t reserved[3];/* Reserved */
volatile uint32_t blk_max; /* (R/ ) Maximum value of block based index */
volatile uint32_t blk_cfg; /* (R/ ) Block configuration */
volatile uint32_t blk_idx; /* (R/W) Index value for accessing block
* based look up table */
volatile uint32_t blk_lutn; /* (R/W) Block based gating
* Look Up Table (LUT) */
volatile uint32_t int_stat; /* (R/ ) Interrupt state */
volatile uint32_t int_clear; /* ( /W) Interrupt clear */
volatile uint32_t int_en; /* (R/W) Interrupt enable */
volatile uint32_t int_info1; /* (R/ ) Interrupt information 1 */
volatile uint32_t int_info2; /* (R/ ) Interrupt information 2 */
volatile uint32_t int_set; /* ( /W) Interrupt set. Debug purpose only */
volatile uint32_t reserved2[997]; /* Reserved */
volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */
volatile uint32_t pidr5; /* (R/ ) Peripheral ID 5 */
volatile uint32_t pidr6; /* (R/ ) Peripheral ID 6 */
volatile uint32_t pidr7; /* (R/ ) Peripheral ID 7 */
volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */
volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */
volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */
volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */
volatile uint32_t cidr0; /* (R/ ) Component ID 0 */
volatile uint32_t cidr1; /* (R/ ) Component ID 1 */
volatile uint32_t cidr2; /* (R/ ) Component ID 2 */
volatile uint32_t cidr3; /* (R/ ) Component ID 3 */
};
/*
* Checks if the address is controlled by the MPC and returns
* the range index in which it is contained.
*
* \param[in] dev MPC device to initalize \ref mpc_sie200_dev_t
* \param[in] addr Address to check if it is controlled by MPC.
* \param[out] addr_range Range index in which it is contained.
*
* \return True if the base is controller by the range list, false otherwise.
*/
static uint32_t is_ctrl_by_range_list(struct mpc_sie200_dev_t* dev, uint32_t addr,
const struct mpc_sie200_memory_range_t** addr_range)
{
uint32_t i;
const struct mpc_sie200_memory_range_t* range;
for(i = 0; i < dev->data->nbr_of_ranges; i++) {
range = dev->data->range_list[i];
if(addr >= range->base && addr <= range->limit) {
*addr_range = range;
return 1;
}
}
return 0;
}
/*
* Gets the masks selecting the bits in the LUT of the MPC corresponding
* to the base address (included) up to the limit address (included)
*
* \param[in] mpc_dev The MPC device.
* \param[in] base Address in a range controlled by this MPC
* (included), aligned on block size.
* \param[in] limit Address in a range controlled by this MPC
* (included), aligned on block size.
* \param[out] range Memory range in which the base address and
* limit are.
* \param[out] first_word_idx Index of the first touched word in the LUT.
* \param[out] nr_words Number of words used in the LUT. If 1, only
* first_word_mask is valid and limit_word_mask
* must not be used.
* \param[out] first_word_mask First word mask in the LUT will be stored here.
* \param[out] limit_word_mask Limit word mask in the LUT will be stored here.
*
* \return Returns error code as specified in \ref mpc_sie200_intern_error_t
*/
static enum mpc_sie200_intern_error_t get_lut_masks(
struct mpc_sie200_dev_t* dev,
const uint32_t base, const uint32_t limit,
const struct mpc_sie200_memory_range_t** range,
uint32_t *first_word_idx,
uint32_t *nr_words,
uint32_t *first_word_mask,
uint32_t *limit_word_mask)
{
const struct mpc_sie200_memory_range_t* base_range;
uint32_t block_size;
uint32_t base_block_idx;
uint32_t base_word_idx;
uint32_t blk_max;
const struct mpc_sie200_memory_range_t* limit_range;
uint32_t limit_block_idx;
uint32_t limit_word_idx;
uint32_t mask;
uint32_t norm_base;
uint32_t norm_limit;
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
/*
* Check that the addresses are within the controlled regions
* of this MPC
*/
if(!is_ctrl_by_range_list(dev, base, &base_range) ||
!is_ctrl_by_range_list(dev, limit, &limit_range)) {
return MPC_SIE200_INTERN_ERR_NOT_IN_RANGE;
}
/* Base and limit should be part of the same range */
if(base_range != limit_range) {
return MPC_SIE200_INTERN_ERR_INVALID_RANGE;
}
*range = base_range;
block_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET));
/* Base and limit+1 addresses must be aligned on the MPC block size */
if(base % block_size || (limit+1) % block_size) {
return MPC_SIE200_INTERN_ERR_NOT_ALIGNED;
}
/*
* Get a normalized address that is an offset from the beginning
* of the lowest range controlled by the MPC
*/
norm_base = (base - base_range->base) + base_range->range_offset;
norm_limit = (limit - base_range->base) + base_range->range_offset;
/*
* Calculate block index and to which 32 bits word it belongs
*/
limit_block_idx = norm_limit/block_size;
limit_word_idx = limit_block_idx/32;
base_block_idx = norm_base/block_size;
base_word_idx = base_block_idx/32;
if(base_block_idx > limit_block_idx) {
return MPC_SIE200_INTERN_ERR_INVALID_RANGE;
}
/* Transmit the information to the caller */
*nr_words = limit_word_idx - base_word_idx + 1;
*first_word_idx = base_word_idx;
/* Limit to the highest block that can be configured */
blk_max = p_mpc->blk_max;
if((limit_word_idx > blk_max) || (base_word_idx > blk_max)) {
return MPC_SIE200_INTERN_ERR_BLK_IDX_TOO_HIGH;
}
/*
* Create the mask for the first word to only select the limit N bits
*/
*first_word_mask = ~((1 << (base_block_idx % 32)) - 1);
/*
* Create the mask for the limit word to select only the first M bits.
*/
*limit_word_mask = (1 << ((limit_block_idx+1) % 32)) - 1;
/*
* If limit_word_mask is 0, it means that the limit touched block index is
* the limit in its word, so the limit word mask has all its bits selected
*/
if(*limit_word_mask == 0) {
*limit_word_mask = 0xFFFFFFFF;
}
/*
* If the blocks to configure are all packed in one word, only
* touch this word.
* Code using the computed masks should test if this mask
* is non-zero, and if so, only use this one instead of the limit_word_mask
* and first_word_mask.
* As the only bits that are the same in both masks are the 1 that we want
* to select, just use XOR to extract them.
*/
if(base_word_idx == limit_word_idx) {
mask = ~(*first_word_mask ^ *limit_word_mask);
*first_word_mask = mask;
*limit_word_mask = mask;
}
return MPC_SIE200_INTERN_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_init(struct mpc_sie200_dev_t* dev,
const struct mpc_sie200_memory_range_t** range_list,
uint8_t nbr_of_ranges)
{
if((range_list == NULL) || (nbr_of_ranges == 0)) {
return MPC_SIE200_INVALID_ARG;
}
dev->data->range_list = range_list;
dev->data->nbr_of_ranges = nbr_of_ranges;
dev->data->state = MPC_SIE200_INITIALIZED;
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_get_block_size(struct mpc_sie200_dev_t* dev,
uint32_t* blk_size)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
if(blk_size == 0) {
return MPC_SIE200_INVALID_ARG;
}
/* Calculate the block size in byte according to the manual */
*blk_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET));
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_config_region(struct mpc_sie200_dev_t* dev,
const uint32_t base,
const uint32_t limit,
enum mpc_sie200_sec_attr_t attr)
{
enum mpc_sie200_intern_error_t error;
uint32_t first_word_idx;
uint32_t first_word_mask;
uint32_t i;
uint32_t limit_word_mask;
uint32_t limit_word_idx;
uint32_t nr_words;
const struct mpc_sie200_memory_range_t* range;
uint32_t word_value;
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
/* Get the bitmasks used to select the bits in the LUT */
error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words,
&first_word_mask, &limit_word_mask);
limit_word_idx = first_word_idx + nr_words - 1;
if(error != MPC_SIE200_INTERN_ERR_NONE) {
/* Map internal error code lower than 0 to a generic errpr */
if(error < 0) {
return MPC_SIE200_ERR_INVALID_RANGE;
}
return (enum mpc_sie200_error_t)error;
}
/*
* The memory range should allow accesses in with the wanted security
* attribute if it requires special attribute for successfull accesses
*/
if(range->attr != attr) {
return MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE;
}
/*
* Starts changing actual configuration so issue DMB to ensure every
* transaction has completed by now
*/
__DMB();
/* Set the block index to the first word that will be updated */
p_mpc->blk_idx = first_word_idx;
/* If only one word needs to be touched in the LUT */
if(nr_words == 1) {
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) {
word_value |= first_word_mask;
} else {
word_value &= ~first_word_mask;
}
/*
* Set the index again because full word read or write could have
* incremented it
*/
p_mpc->blk_idx = first_word_idx;
p_mpc->blk_lutn = word_value;
/* Commit the configuration change */
__DSB();
__ISB();
return MPC_SIE200_ERR_NONE;
}
/* First word */
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) {
word_value |= first_word_mask;
} else {
word_value &= ~first_word_mask;
}
/*
* Set the index again because full word read or write could have
* incremented it
*/
p_mpc->blk_idx = first_word_idx;
/* Partially configure the first word */
p_mpc->blk_lutn = word_value;
/* Fully configure the intermediate words if there are any */
for(i=first_word_idx+1; i<limit_word_idx; i++) {
p_mpc->blk_idx = i;
if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) {
p_mpc->blk_lutn = 0xFFFFFFFF;
} else {
p_mpc->blk_lutn = 0x00000000;
}
}
/* Partially configure the limit word */
p_mpc->blk_idx = limit_word_idx;
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE200_SEC_ATTR_NONSECURE) {
word_value |= limit_word_mask;
} else {
word_value &= ~limit_word_mask;
}
p_mpc->blk_idx = limit_word_idx;
p_mpc->blk_lutn = word_value;
/* Commit the configuration change */
__DSB();
__ISB();
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_get_region_config(
struct mpc_sie200_dev_t* dev,
uint32_t base, uint32_t limit,
enum mpc_sie200_sec_attr_t* attr)
{
enum mpc_sie200_sec_attr_t attr_prev;
uint32_t block_size;
uint32_t block_size_mask;
enum mpc_sie200_intern_error_t error;
uint32_t first_word_idx;
uint32_t first_word_mask;
uint32_t i;
uint32_t limit_word_idx;
uint32_t limit_word_mask;
uint32_t nr_words;
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
const struct mpc_sie200_memory_range_t* range;
uint32_t word_value;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
if(attr == 0) {
return MPC_SIE200_INVALID_ARG;
}
/*
* Initialize the security attribute to mixed in case of early
* termination of this function. A caller that does not check the
* returned error will act as if it does not know anything about the
* region queried, which is the safest bet
*/
*attr = MPC_SIE200_SEC_ATTR_MIXED;
/*
* If the base and limit are not aligned, align them and make sure
* that the resulting region fully includes the original region
*/
block_size = (1 << (p_mpc->blk_cfg + MPC_SIE200_BLK_CFG_OFFSET));
block_size_mask = block_size - 1;
base &= ~(block_size_mask);
limit &= ~(block_size_mask);
limit += block_size - 1; /* Round to the upper block address,
* and then remove one to get the preceding
* address.
*/
/* Get the bitmasks used to select the bits in the LUT */
error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words,
&first_word_mask, &limit_word_mask);
limit_word_idx = first_word_idx+nr_words - 1;
if(error != MPC_SIE200_INTERN_ERR_NONE) {
/* Map internal error code lower than 0 to generic error */
if(error < 0) {
return MPC_SIE200_ERR_INVALID_RANGE;
}
return (enum mpc_sie200_error_t)error;
}
/* Set the block index to the first word that will be updated */
p_mpc->blk_idx = first_word_idx;
/* If only one word needs to be touched in the LUT */
if(nr_words == 1) {
word_value = p_mpc->blk_lutn;
word_value &= first_word_mask;
if(word_value == 0) {
*attr = MPC_SIE200_SEC_ATTR_SECURE;
/*
* If there are differences between the mask and the word value,
* it means that the security attributes of blocks are mixed
*/
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
} else {
*attr = MPC_SIE200_SEC_ATTR_NONSECURE;
}
return MPC_SIE200_ERR_NONE;
}
/* Get the partial configuration of the first word */
word_value = p_mpc->blk_lutn & first_word_mask;
if(word_value == 0x00000000) {
*attr = MPC_SIE200_SEC_ATTR_SECURE;
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
/*
* Bail out as the security attribute will be the same regardless
* of the configuration of other blocks
*/
return MPC_SIE200_ERR_NONE;
} else {
*attr = MPC_SIE200_SEC_ATTR_NONSECURE;
}
/*
* Store the current found attribute, to check that all the blocks indeed
* have the same security attribute.
*/
attr_prev = *attr;
/* Get the configuration of the intermediate words if there are any */
for(i=first_word_idx+1; i<limit_word_idx; i++) {
p_mpc->blk_idx = i;
word_value = p_mpc->blk_lutn;
if(word_value == 0x00000000) {
*attr = MPC_SIE200_SEC_ATTR_SECURE;
} else if(word_value == 0xFFFFFFFF) {
*attr = MPC_SIE200_SEC_ATTR_NONSECURE;
} else {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
return MPC_SIE200_ERR_NONE;
}
/* If the attribute is different than the one found before, bail out */
if(*attr != attr_prev) {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
return MPC_SIE200_ERR_NONE;
}
attr_prev = *attr;
}
/* Get the partial configuration of the limit word */
p_mpc->blk_idx = limit_word_idx;
word_value = p_mpc->blk_lutn & limit_word_mask;
if(word_value == 0x00000000) {
*attr = MPC_SIE200_SEC_ATTR_SECURE;
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
return MPC_SIE200_ERR_NONE;
} else {
*attr = MPC_SIE200_SEC_ATTR_NONSECURE;
}
if(*attr != attr_prev) {
*attr = MPC_SIE200_SEC_ATTR_MIXED;
return MPC_SIE200_ERR_NONE;
}
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_get_ctrl(struct mpc_sie200_dev_t* dev,
uint32_t* ctrl_val)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
if(ctrl_val == 0) {
return MPC_SIE200_INVALID_ARG;
}
*ctrl_val = p_mpc->ctrl;
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_set_ctrl(struct mpc_sie200_dev_t* dev,
uint32_t mpc_ctrl)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
p_mpc->ctrl = mpc_ctrl;
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_get_sec_resp(struct mpc_sie200_dev_t* dev,
enum mpc_sie200_sec_resp_t* sec_rep)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
if(sec_rep == 0) {
return MPC_SIE200_INVALID_ARG;
}
if(p_mpc->ctrl & MPC_SIE200_CTRL_SEC_RESP) {
*sec_rep = MPC_SIE200_RESP_BUS_ERROR;
return MPC_SIE200_ERR_NONE;
}
*sec_rep = MPC_SIE200_RESP_RAZ_WI;
return MPC_SIE200_ERR_NONE;
}
enum mpc_sie200_error_t mpc_sie200_irq_enable(struct mpc_sie200_dev_t* dev)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
p_mpc->int_en |= MPC_SIE200_INT_EN;
return MPC_SIE200_ERR_NONE;
}
void mpc_sie200_irq_disable(struct mpc_sie200_dev_t* dev)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
p_mpc->int_en &= ~MPC_SIE200_INT_EN;
}
void mpc_sie200_clear_irq(struct mpc_sie200_dev_t* dev)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
p_mpc->int_clear = MPC_SIE200_INT_EN;
}
uint32_t mpc_sie200_irq_state(struct mpc_sie200_dev_t* dev)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
return (p_mpc->int_stat & MPC_SIE200_INT_STAT);
}
enum mpc_sie200_error_t mpc_sie200_lock_down(struct mpc_sie200_dev_t* dev)
{
struct mpc_sie200_reg_map_t* p_mpc =
(struct mpc_sie200_reg_map_t*)dev->cfg->base;
if(!(dev->data->state & MPC_SIE200_INITIALIZED)) {
return MPC_SIE200_NOT_INIT;
}
p_mpc->ctrl |= (MPC_SIE200_CTRL_AUTOINCREMENT
| MPC_SIE200_CTRL_SEC_LOCK_DOWN);
return MPC_SIE200_ERR_NONE;
}

View File

@ -1,282 +0,0 @@
/*
* Copyright (c) 2016-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file mpc_sie200_drv.h
* \brief Generic driver for ARM SIE 200 Memory Protection
* Controllers (MPC).
*/
#ifndef __MPC_SIE_200_DRV_H__
#define __MPC_SIE_200_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Error code returned by the driver functions */
enum mpc_sie200_error_t {
MPC_SIE200_ERR_NONE, /*!< No error */
MPC_SIE200_INVALID_ARG, /*!< MPC invalid input arguments */
MPC_SIE200_NOT_INIT, /*!< MPC not initialized */
MPC_SIE200_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range
* controlled by the MPC */
MPC_SIE200_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size
* of this MPC */
MPC_SIE200_ERR_INVALID_RANGE, /*!< The given address range to configure
* is invalid. This could be because:
* - The base and limit swapped
* - The base and limit addresses
* are in different ranges */
MPC_SIE200_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be
* accessed with the wanted
* security attributes */
};
/* Security attribute used in various place of the API */
enum mpc_sie200_sec_attr_t {
MPC_SIE200_SEC_ATTR_SECURE, /*!< Secure attribute */
MPC_SIE200_SEC_ATTR_NONSECURE, /*!< Non-secure attribute */
/*!< Used when getting the configuration of a memory range and some blocks
* are secure whereas some other are non secure */
MPC_SIE200_SEC_ATTR_MIXED,
};
/* What can happen when trying to do an illegal memory access */
enum mpc_sie200_sec_resp_t {
MPC_SIE200_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */
MPC_SIE200_RESP_BUS_ERROR /*!< Bus error */
};
/* Description of a memory range controlled by the MPC */
struct mpc_sie200_memory_range_t {
const uint32_t base; /*!< Base address (included in the range) */
const uint32_t limit; /*!< Limit address (included in the range) */
const uint32_t range_offset; /*!< Offset of current range area to the 0
point of the whole area (the sum of the
sizes of the previous memory ranges
covered by the same MPC) */
const enum mpc_sie200_sec_attr_t attr; /*!< Optional security attribute
needed to be matched when
accessing this range.
For example, the non-secure
alias of a memory region can not
be accessed using secure access,
and configuring the MPC to
secure using that range will not
be permitted by the driver. */
};
/* ARM MPC SIE 200 device configuration structure */
struct mpc_sie200_dev_cfg_t {
const uint32_t base; /*!< MPC base address */
};
/* ARM MPC SIE 200 device data structure */
struct mpc_sie200_dev_data_t {
const struct mpc_sie200_memory_range_t** range_list; /*!< Array of pointers
to memory ranges
controlled by
the MPC */
uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */
uint8_t state; /*!< Indicates if the MPC driver
is initialized and enabled */
uint16_t reserved; /*!< 32 bits alignment */
};
/* ARM MPC SIE 200 device structure */
struct mpc_sie200_dev_t {
const struct mpc_sie200_dev_cfg_t* const cfg; /*!< MPC configuration */
struct mpc_sie200_dev_data_t* const data; /*!< MPC data */
};
/**
* \brief Initializes a MPC device.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[in] range_list List of memory ranges controller by the MPC
* (\ref mpc_sie200_memory_range_t). This list can not
* freed after the initializations.
* \param[in] nbr_of_ranges Number of memory ranges
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_init(struct mpc_sie200_dev_t* dev,
const struct mpc_sie200_memory_range_t** range_list,
uint8_t nbr_of_ranges);
/**
* \brief Gets MPC block size. All regions must be aligned on this block
* size (base address and limit+1 address).
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[out] blk_size MPC block size
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_get_block_size(struct mpc_sie200_dev_t* dev,
uint32_t* blk_size);
/**
* \brief Configures a memory region (base and limit included).
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[in] base Base address of the region to poll. This bound is
* included. It does not need to be aligned in any way.
*
* \param[in] limit Limit address of the region to poll. This bound is
* included. (limit+1) does not need to be aligned
* in any way.
* \param[in] attr Security attribute of the region. If the region has mixed
* secure/non-secure, a special value is returned
* (\ref mpc_sie200_sec_attr_t).
*
* In case base and limit+1 addresses are not aligned on
* the block size, the enclosing region with base and
* limit+1 aligned on block size will be queried.
* In case of early termination of the function (error), the
* security attribute will be set to MPC_SIE200_ATTR_MIXED.
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_config_region(struct mpc_sie200_dev_t* dev,
const uint32_t base,
const uint32_t limit,
enum mpc_sie200_sec_attr_t attr);
/**
* \brief Gets a memory region configuration(base and limit included).
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[in] base Base address of the region to get the configuration.
* \param[in] limit Limit address of the region to get the configuration.
* \param[out] attr Security attribute of the region
* \ref mpc_sie200_sec_attr_t
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_get_region_config(
struct mpc_sie200_dev_t* dev,
uint32_t base,
uint32_t limit,
enum mpc_sie200_sec_attr_t* attr);
/**
* \brief Gets the MPC control value.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[out] ctrl_val Current MPC control value.
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_get_ctrl(struct mpc_sie200_dev_t* dev,
uint32_t* ctrl_val);
/**
* \brief Sets the MPC control value.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[in] mpc_ctrl New MPC control value
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_set_ctrl(struct mpc_sie200_dev_t* dev,
uint32_t mpc_ctrl);
/**
* \brief Gets the configured secure response.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
* \param[out] sec_rep Configured secure response (\ref mpc_sie200_sec_resp_t).
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_get_sec_resp(struct mpc_sie200_dev_t* dev,
enum mpc_sie200_sec_resp_t* sec_rep);
/**
* \brief Enables MPC interrupt.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_irq_enable(struct mpc_sie200_dev_t* dev);
/**
* \brief Disables MPC interrupt
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie200_irq_disable(struct mpc_sie200_dev_t* dev);
/**
* \brief Clears MPC interrupt.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie200_clear_irq(struct mpc_sie200_dev_t* dev);
/**
* \brief Returns the MPC interrupt state.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
*
* \return Returns 1 if the interrupt is active, 0 otherwise.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t mpc_sie200_irq_state(struct mpc_sie200_dev_t* dev);
/**
* \brief Locks down the MPC configuration.
*
* \param[in] dev MPC device \ref mpc_sie200_dev_t
*
* \return Returns error code as specified in \ref mpc_sie200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie200_error_t mpc_sie200_lock_down(struct mpc_sie200_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __MPC_SIE_200_DRV_H__ */

View File

@ -1,138 +0,0 @@
/*
* Copyright (c) 2017-2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "mpu_armv8m_drv.h"
#include "cmsis_cpu.h"
/*
* FixMe:
* This is a beta quality driver for MPU in v8M. To be finalized.
*/
enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
uint32_t privdef_en,
uint32_t hfnmi_en)
{
/*No error checking*/
MPU_Type *mpu = (MPU_Type *)dev->base;
mpu->CTRL =
(privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
(hfnmi_en ? MPU_CTRL_HFNMIENA_Msk : 0);
/*Ensure all configuration is written before enable*/
mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
/* Enable MPU before next instruction */
__asm("DSB");
__asm("ISB");
return MPU_ARMV8M_OK;
}
enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
/* Reset all fields as enable does full setup */
mpu->CTRL = 0;
return MPU_ARMV8M_OK;
}
enum mpu_armv8m_error_t mpu_armv8m_region_enable(
struct mpu_armv8m_dev_t *dev,
struct mpu_armv8m_region_cfg_t *region_cfg)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
uint32_t ctrl_before;
uint32_t base_cfg;
uint32_t limit_cfg;
/*FIXME : Add complete error checking*/
if ((region_cfg->region_base & ~MPU_RBAR_BASE_Msk) != 0) {
return MPU_ARMV8M_ERROR;
}
/* region_limit doesn't need to be aligned but the scatter
* file needs to be setup to ensure that partitions do not overlap.
*/
ctrl_before = mpu->CTRL;
mpu->CTRL = 0;
mpu->RNR = region_cfg->region_nr & MPU_RNR_REGION_Msk;
/* This 0s the lower bits of the base address */
base_cfg = region_cfg->region_base & MPU_RBAR_BASE_Msk;
base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
mpu->RBAR = base_cfg;
/*This 0s the lower bits of base address but they are treated as 1 */
limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
/*FIXME: Enable the memory attr setting */
limit_cfg |= MPU_RLAR_EN_Msk;
mpu->RLAR = limit_cfg;
/*Restore main MPU control*/
mpu->CTRL = ctrl_before;
/* Enable MPU before the next instruction */
__asm("DSB");
__asm("ISB");
return ret_val;
}
enum mpu_armv8m_error_t mpu_armv8m_region_disable(
struct mpu_armv8m_dev_t *dev,
uint32_t region_nr)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
uint32_t ctrl_before;
/*FIXME : Add complete error checking*/
ctrl_before = mpu->CTRL;
mpu->CTRL = 0;
mpu->RNR = region_nr & MPU_RNR_REGION_Msk;
mpu->RBAR = 0;
mpu->RLAR = 0;
/*Restore main MPU control*/
mpu->CTRL = ctrl_before;
return ret_val;
}
enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
while (i > 0) {
mpu_armv8m_region_disable(dev, i-1);
i--;
}
return MPU_ARMV8M_OK;
}

View File

@ -1,128 +0,0 @@
/*
* Copyright (c) 2017-2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __MPU_ARMV8M_DRV_H__
#define __MPU_ARMV8M_DRV_H__
#include <stdint.h>
#include "cmsis.h"
#define PRIVILEGED_DEFAULT_ENABLE 1
#define HARDFAULT_NMI_ENABLE 1
struct mpu_armv8m_dev_t {
const uint32_t base;
};
enum mpu_armv8m_error_t {
MPU_ARMV8M_OK,
MPU_ARMV8M_ERROR
};
enum mpu_armv8m_attr_exec_t {
MPU_ARMV8M_XN_EXEC_OK,
MPU_ARMV8M_XN_EXEC_NEVER
};
enum mpu_armv8m_attr_access_t {
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
MPU_ARMV8M_AP_RO_PRIV_ONLY,
MPU_ARMV8M_AP_RO_PRIV_UNPRIV
};
enum mpu_armv8m_attr_shared_t {
MPU_ARMV8M_SH_NONE,
MPU_ARMV8M_SH_UNUSED,
MPU_ARMV8M_SH_OUTER,
MPU_ARMV8M_SH_INNER
};
struct mpu_armv8m_region_cfg_t {
uint32_t region_nr;
uint32_t region_base;
uint32_t region_limit;
enum mpu_armv8m_attr_exec_t attr_exec;
enum mpu_armv8m_attr_access_t attr_access;
enum mpu_armv8m_attr_shared_t attr_sh;
};
struct mpu_armv8m_region_cfg_raw_t {
uint32_t region_nr;
uint32_t region_base;
uint32_t region_limit;
};
/**
* \brief Enable MPU
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] privdef_en privilege default region 1:enable 0:disable
* \param[in] hfnmi_en mpu for hard fault & nmi 1:enable 0:disable
*
* \return Error code \ref mpu_armv8m_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
uint32_t privdef_en,
uint32_t hfnmi_en);
/**
* \brief Disable MPU
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
/**
* \brief Disable MPU and clean all regions
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
/**
* \brief Enable MPU Region
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] region_cfg MPU region config \ref mpu_armv8m_region_cfg_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_region_enable(
struct mpu_armv8m_dev_t *dev,
struct mpu_armv8m_region_cfg_t *region_cfg);
/**
* \brief Disable MPU Region
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] region_nr Region number
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_region_disable(
struct mpu_armv8m_dev_t *dev,
uint32_t region_nr);
#endif /* __MPU_ARMV8M_DRV_H__ */

View File

@ -1,325 +0,0 @@
/*
* Copyright (c) 2017-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ppc_sse200_drv.h"
/* SPCTRL PPCs control memory mapped registers access structure */
struct arm_spctrl_ppc_sse200_t {
volatile uint32_t reserved[8];
volatile uint32_t secppcintstat; /* Secure PPC Interrupt Status */
volatile uint32_t secppcintclr; /* Secure PPC Interrupt Clear */
volatile uint32_t secppcinten; /* Secure PPC Interrupt Enable */
volatile uint32_t reserved1[9];
volatile uint32_t ahbnsppc0; /* Non-Secure Access AHB slave Peripheral
Protection Control #0 */
volatile uint32_t reserved2[3]; /* Reserved for Future Non-secure Access
AHB Slave Peripheral Protection
Control */
volatile uint32_t ahbnsppcexp0; /* Expansion 0 Non_Secure Access AHB
slave Peripheral Protection Control */
volatile uint32_t ahbnsppcexp1; /* Expansion 1 Non_Secure Access AHB
slave Peripheral Protection Control */
volatile uint32_t ahbnsppcexp2; /* Expansion 2 Non_Secure Access AHB
slave Peripheral Protection Control */
volatile uint32_t ahbnsppcexp3; /* Expansion 3 Non_Secure Access AHB
slave Peripheral Protection Control */
volatile uint32_t apbnsppc0; /* Non-Secure Access APB slave Peripheral
Protection Control 0 */
volatile uint32_t apbnsppc1; /* Non-Secure Access APB slave Peripheral
Protection Control 1 */
volatile uint32_t reserved3[2]; /* Non-Secure Access APB slave Peripheral
Protection Control [3:1] */
volatile uint32_t apbnsppcexp0; /* Expansion 0 Non_Secure Access APB
slave Peripheral Protection Control */
volatile uint32_t apbnsppcexp1; /* Expansion 1 Non_Secure Access APB
slave Peripheral Protection Control */
volatile uint32_t apbnsppcexp2; /* Expansion 2 Non_Secure Access APB
slave Peripheral Protection Control */
volatile uint32_t apbnsppcexp3; /* Expansion 3 Non_Secure Access APB
slave Peripheral Protection Control */
volatile uint32_t ahbspppc0; /* Secure Unprivileged Access AHB slave
Peripheral Protection Control 0 */
volatile uint32_t reserved4[3]; /* Reserved for Future Secure Unprivileged
Access AHB slave Peripheral Protection
Control */
volatile uint32_t ahbspppcexp0; /* Expansion 0 Secure Unprivileged Access
AHB slave Peripheral Protection
Control */
volatile uint32_t ahbspppcexp1; /* Expansion 1 Secure Unprivileged Access
AHB slave Peripheral Protection
Control */
volatile uint32_t ahbspppcexp2; /* Expansion 2 Secure Unprivileged Access
AHB slave Peripheral Protection
Control */
volatile uint32_t ahbspppcexp3; /* Expansion 3 Secure Unprivileged Access
AHB slave Peripheral Protection
Control */
volatile uint32_t apbspppc0; /* Secure Unprivileged Access APB slave
Peripheral 0 */
volatile uint32_t apbspppc1; /* Secure Unprivileged Access APB slave
Peripheral 1 */
volatile uint32_t reserved5[2]; /* Reserved for Future Secure Unprivileged
Access APB slave Peripheral Protection
Control */
volatile uint32_t apbspppcexp0; /* Expansion 0 Secure Unprivileged Access
APB slave Peripheral Protection
Control */
volatile uint32_t apbspppcexp1; /* Expansion 1 Secure Unprivileged Access
APB slave Peripheral Protection
Control */
volatile uint32_t apbspppcexp2; /* Expansion 2 Secure Unprivileged Access
APB slave Peripheral Protection
Control */
volatile uint32_t apbspppcexp3; /* Expansion 3 Secure Unprivileged Access
APB slave Peripheral Protection
Control */
};
/* NSPCTRL PPCs memory mapped register access structure */
struct arm_nspctrl_ppc_sse200_t {
volatile uint32_t reserved[36];
volatile uint32_t ahbnspppc0;
volatile uint32_t reserved1[3];
volatile uint32_t ahbnspppcexp0;
volatile uint32_t ahbnspppcexp1;
volatile uint32_t ahbnspppcexp2;
volatile uint32_t ahbnspppcexp3;
volatile uint32_t apbnspppc0;
volatile uint32_t apbnspppc1;
volatile uint32_t reserved2[2];
volatile uint32_t apbnspppcexp0;
volatile uint32_t apbnspppcexp1;
volatile uint32_t apbnspppcexp2;
volatile uint32_t apbnspppcexp3;
};
/* PPC interrupt position mask */
#define APB_PPC0_INT_POS_MASK (1UL << 0)
#define APB_PPC1_INT_POS_MASK (1UL << 1)
/* Reseved bits 2:3 */
#define APB_PPCEXP0_INT_POS_MASK (1UL << 4)
#define APB_PPCEXP1_INT_POS_MASK (1UL << 5)
#define APB_PPCEXP2_INT_POS_MASK (1UL << 6)
#define APB_PPCEXP3_INT_POS_MASK (1UL << 7)
/* Reseved bits 8:15 */
#define AHB_PPC0_INT_POS_MASK (1UL << 16)
/* Reseved bits 17:19 */
#define AHB_PPCEXP0_INT_POS_MASK (1UL << 20)
#define AHB_PPCEXP1_INT_POS_MASK (1UL << 21)
#define AHB_PPCEXP2_INT_POS_MASK (1UL << 22)
#define AHB_PPCEXP3_INT_POS_MASK (1UL << 23)
/* Reseved bits 24:31 */
/* ARM PPC state definitions */
#define PPC_SSE200_INITIALIZED (1 << 0)
/* Default peripheral states */
#define SECURE_AS_DEFAULT_PERIPHERAL_STATE 1
#define PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE 1
void ppc_sse200_init(struct ppc_sse200_dev_t* dev,
enum ppc_sse200_name_t ppc_name)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
struct arm_nspctrl_ppc_sse200_t* p_nspctrl =
(struct arm_nspctrl_ppc_sse200_t*)dev->cfg->nspctrl_base;
switch(ppc_name) {
case AHB_PPC0:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppc0;
dev->data->p_sp_ppc = &p_spctrl->ahbspppc0;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppc0;
dev->data->int_bit_mask = AHB_PPC0_INT_POS_MASK;
break;
case AHB_PPC_EXP0:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp0;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp0;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp0;
dev->data->int_bit_mask = AHB_PPCEXP0_INT_POS_MASK;
break;
case AHB_PPC_EXP1:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp1;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp1;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp1;
dev->data->int_bit_mask = AHB_PPCEXP1_INT_POS_MASK;
break;
case AHB_PPC_EXP2:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp2;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp2;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp2;
dev->data->int_bit_mask = AHB_PPCEXP2_INT_POS_MASK;
break;
case AHB_PPC_EXP3:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp3;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp3;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp3;
dev->data->int_bit_mask = AHB_PPCEXP3_INT_POS_MASK;
break;
case APB_PPC0:
dev->data->p_ns_ppc = &p_spctrl->apbnsppc0;
dev->data->p_sp_ppc = &p_spctrl->apbspppc0;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc0;
dev->data->int_bit_mask = APB_PPC0_INT_POS_MASK;
break;
case APB_PPC1:
dev->data->p_ns_ppc = &p_spctrl->apbnsppc1;
dev->data->p_sp_ppc = &p_spctrl->apbspppc1;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc1;
dev->data->int_bit_mask = APB_PPC1_INT_POS_MASK;
break;
case APB_PPC_EXP0:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp0;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp0;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp0;
dev->data->int_bit_mask = APB_PPCEXP0_INT_POS_MASK;
break;
case APB_PPC_EXP1:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp1;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp1;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp1;
dev->data->int_bit_mask = APB_PPCEXP1_INT_POS_MASK;
break;
case APB_PPC_EXP2:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp2;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp2;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp2;
dev->data->int_bit_mask = APB_PPCEXP2_INT_POS_MASK;
break;
case APB_PPC_EXP3:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp3;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp3;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp3;
dev->data->int_bit_mask = APB_PPCEXP3_INT_POS_MASK;
break;
/* default: The default is not defined intentionally to force the
* compiler to check that all enumeration values are
* covered in the switch.*/
}
dev->data->state = PPC_SSE200_INITIALIZED;
}
enum ppc_sse200_error_t ppc_sse200_config_peripheral(
struct ppc_sse200_dev_t* dev,
uint8_t periph,
enum ppc_sse200_sec_attr_t sec_attr,
enum ppc_sse200_priv_attr_t priv_attr)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PPC_SSE200_NOT_INIT;
}
if(sec_attr == PPC_SSE200_SECURE_ONLY) {
/* Sets secure attribute */
*(dev->data->p_ns_ppc) &= ~(1U << periph);
/* Uses secure unprivileged access address (SPCTRL) to set privilege
* attribute */
if(priv_attr == PPC_SSE200_PRIV_ONLY) {
*(dev->data->p_sp_ppc) &= ~(1U << periph);
} else {
*(dev->data->p_sp_ppc) |= (1U << periph);
}
} else {
/* Sets secure attribute */
*(dev->data->p_ns_ppc) |= (1U << periph);
/* Uses non-secure unprivileged access address (NSPCTRL) to set
* privilege attribute */
if(priv_attr == PPC_SSE200_PRIV_ONLY) {
*(dev->data->p_nsp_ppc) &= ~(1U << periph);
} else {
*(dev->data->p_nsp_ppc) |= (1U << periph);
}
}
return PPC_SSE200_ERR_NONE;
}
uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev,
uint8_t periph)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return SECURE_AS_DEFAULT_PERIPHERAL_STATE;
}
return ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0);
}
uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev,
uint8_t periph)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE;
}
if ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0) {
/* Returns secure unprivileged access address (SPCTRL) */
return ((*(dev->data->p_sp_ppc) & (1U << periph)) == 0);
} else {
/* Returns non-secure unprivileged access address (NSPCTRL) */
return ((*(dev->data->p_nsp_ppc) & (1U << periph)) == 0);
}
}
enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PPC_SSE200_NOT_INIT;
}
p_spctrl->secppcinten |= dev->data->int_bit_mask;
return PPC_SSE200_ERR_NONE;
}
void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state == PPC_SSE200_INITIALIZED) {
p_spctrl->secppcinten &= ~(dev->data->int_bit_mask);
}
}
void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state == PPC_SSE200_INITIALIZED) {
p_spctrl->secppcintclr = dev->data->int_bit_mask;
}
}
uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return 0;
}
return ((p_spctrl->secppcintstat & dev->data->int_bit_mask) != 0);
}

View File

@ -1,192 +0,0 @@
/*
* Copyright (c) 2017-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file ppc_sse200_drv.h
* \brief Generic driver for ARM SEE 200 Peripheral Protection
* Controllers (PPC).
*/
#ifndef __PPC_SSE_200_DRV_H__
#define __PPC_SSE_200_DRV_H__
#include <stdint.h>
/* Secure Privilege Control Block aka SPCTRL */
/* Non-Secure Privilege Control Block aka NSPCTRL */
/* ARM TrustZone PPC device configuration structure */
struct ppc_sse200_dev_cfg_t {
uint32_t const spctrl_base; /*!< SPCTRL base address */
uint32_t const nspctrl_base; /*!< NSPCTRL base address */
};
/* ARM TrustZone PPC device data structure */
struct ppc_sse200_dev_data_t {
volatile uint32_t* p_ns_ppc; /*!< Pointer to non-secure register */
volatile uint32_t* p_sp_ppc; /*!< Pointer to secure unprivileged
register */
volatile uint32_t* p_nsp_ppc; /*!< Pointer to non-secure unprivileged
register */
uint32_t int_bit_mask; /*!< Interrupt bit mask */
uint8_t state; /*!< Indicates if the PPC driver
is initialized */
uint8_t reserved[3]; /*!< 32 bits alignment */
};
/* ARM PPC device structure */
struct ppc_sse200_dev_t {
const struct ppc_sse200_dev_cfg_t* const cfg; /*!< PPC configuration */
struct ppc_sse200_dev_data_t* const data; /*!< PPC data */
};
/* Security attribute used to configure the peripheral */
enum ppc_sse200_sec_attr_t {
PPC_SSE200_SECURE_ONLY, /*! Secure access */
PPC_SSE200_NONSECURE_ONLY, /*! Non-secure access */
};
/* Privilege attribute used to configure the peripheral */
enum ppc_sse200_priv_attr_t {
PPC_SSE200_PRIV_AND_NONPRIV, /*! Privilege and non-Privilege access */
PPC_SSE200_PRIV_ONLY, /*! Privilege only access */
};
/* ARM PPC error codes */
enum ppc_sse200_error_t {
PPC_SSE200_ERR_NONE = 0, /*!< No error */
PPC_SSE200_NOT_INIT, /*!< PPC not initialized */
};
/* ARM PPC names */
enum ppc_sse200_name_t {
AHB_PPC0 = 0, /*!< AHB PPC0 */
AHB_PPC_EXP0, /*!< Expansion 0 AHB PPC */
AHB_PPC_EXP1, /*!< Expansion 1 AHB PPC */
AHB_PPC_EXP2, /*!< Expansion 2 AHB PPC */
AHB_PPC_EXP3, /*!< Expansion 3 AHB PPC */
APB_PPC0, /*!< APB PPC0 */
APB_PPC1, /*!< APB PPC1 */
APB_PPC_EXP0, /*!< Expansion 0 APB PPC */
APB_PPC_EXP1, /*!< Expansion 1 APB PPC */
APB_PPC_EXP2, /*!< Expansion 2 APB PPC */
APB_PPC_EXP3 /*!< Expansion 3 APB PPC */
};
/**
* \brief Initialize the PPC device.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] ppc_name PPC name \ref ppc_sse200_name_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_init(struct ppc_sse200_dev_t* dev,
enum ppc_sse200_name_t ppc_name);
/**
* \brief Configures the PPC device.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
* \param[in] sec_attr Secure attribute value.
* \param[in] priv_attr Privilege attribute value.
*
* \return Returns error code as specified in \ref ppc_sse200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum ppc_sse200_error_t ppc_sse200_config_peripheral(
struct ppc_sse200_dev_t* dev,
uint8_t periph,
enum ppc_sse200_sec_attr_t sec_attr,
enum ppc_sse200_priv_attr_t priv_attr);
/**
* \brief Checks if the peripheral is configured as secure or non-secure.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
*
* \return Returns 1 for secure and 0 for non-secure.
* If the driver is not initalized the return value is 1 (secure) as
* it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev,
uint8_t periph);
/**
* \brief Checks if the peripheral is configured as Privilege only or
* Privilege and non-Privilege access mode.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
*
* \return Returns 1 for Privilege only configuration and 0 for Privilege and
* non-Privilege access.
* If the driver is not initalized the return of this function is
* 1 (Privilege only) as it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev,
uint8_t periph);
/**
* \brief Enables PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \return Returns error code as specified in \ref ppc_sse200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev);
/**
* \brief Disables PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev);
/**
* \brief Clears PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev);
/**
* \brief Returns the PPC interrupt state.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \return Returns 1 if the interrupt is active and otherwise 0.
* If the driver is not initalized the return of this function is
* 0 (not active) as it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev);
#endif /* __PPC_SSE_200_DRV_H__ */

View File

@ -1,757 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
/* Use memcpy */
#include <string.h>
#include "qspi_ip6514e_drv.h"
/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
/** Getter bit manipulation macro */
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
#define WORD_ALIGN_4B_MASK 0x3U /* Mask the first 2 bits */
#define IS_ADDR_ALIGNED(ADDR) (((uint32_t)(ADDR) & (WORD_ALIGN_4B_MASK)) == 0U)
#define BITS_PER_BYTE 8U
#define BITS_PER_WORD 32U
#define CFG_READS true
#define CFG_WRITES false
#define ARG_NOT_USED 0
#define ARG_PTR_NOT_USED NULL
#define DATA_REG_NUMBER 2U
#define DATA_REG_LOWER 0U
#define DATA_REG_UPPER 1U
#define ERROR_VALUE 0xFFFFFFFFU
/**
* \brief QSPI IP6514E register map structure
*/
struct _qspi_ip6514e_reg_map_t {
volatile uint32_t qspi_cfg; /*!< 0x00 (R/W) */
volatile uint32_t device_read_inst; /*!< 0x04 (R/W) */
volatile uint32_t device_write_inst; /*!< 0x08 (R/W) */
volatile uint32_t hidden1[2];
volatile uint32_t device_size; /*!< 0x14 (R/W) */
volatile uint32_t hidden2[3];
volatile uint32_t remap_addr; /*!< 0x24 (R/W) */
volatile uint32_t hidden3[26];
volatile uint32_t flash_cmd_ctrl; /*!< 0x90 (R/W) */
volatile uint32_t flash_cmd_addr; /*!< 0x94 (R/W) */
volatile uint32_t hidden4[2];
volatile uint32_t flash_cmd_read_data_lower; /*!< 0xA0 (R/ ) */
volatile uint32_t flash_cmd_read_data_upper; /*!< 0xA4 (R/ ) */
volatile uint32_t flash_cmd_write_data_lower; /*!< 0xA8 (R/W) */
volatile uint32_t flash_cmd_write_data_upper; /*!< 0xAC (R/W) */
volatile uint32_t hidden5[2];
};
/** QSPI Configuration register description (offset 0x00) */
#define QSPI_CFG_ENABLE_POS 0U
#define QSPI_CFG_ENABLE_ADDR_REMAP_POS 16U
#define QSPI_CFG_BAUD_DIV_POS 19U
#define QSPI_CFG_BAUD_DIV_MIN 2U
#define QSPI_CFG_BAUD_DIV_MAX 32U
#define QSPI_CFG_BAUD_DIV_BITS 4U
#define QSPI_CFG_IDLE_POS 31U
/**
* Device Read/Write Instruction registers description (offset 0x04 and 0x08).
* These values are the same for the Device Read Instruction register at offset
* 0x04 and the Device Write Instruction register at offset 0x08.
*/
#define DEVICE_READ_WRITE_INST_OPCODE_POS 0U
#define DEVICE_READ_INST_INST_TYPE_POS 8U /* Only applies to the Read
* register. */
#define DEVICE_READ_WRITE_INST_ADDR_TYPE_POS 12U
#define DEVICE_READ_WRITE_INST_DATA_TYPE_POS 16U
#define DEVICE_READ_WRITE_INST_MODE_QSPI 2U
#define DEVICE_READ_WRITE_INST_MODE_DSPI 1U
#define DEVICE_READ_WRITE_INST_MODE_SPI 0U
#define DEVICE_READ_WRITE_INST_MODE_BITS 2U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS 24U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS 5U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX 31U
/** Device Size Configuration register description (offset 0x14) */
#define DEVICE_SIZE_ADDR_BYTES_POS 0U
#define DEVICE_SIZE_ADDR_BYTES_MIN 1U
#define DEVICE_SIZE_ADDR_BYTES_MAX 16U
#define DEVICE_SIZE_ADDR_BYTES_BITS 4U
#define DEVICE_SIZE_PAGE_BYTES_POS 4U
#define DEVICE_SIZE_PAGE_BYTES_MAX 4095U
#define DEVICE_SIZE_PAGE_BYTES_BITS 12U
/** Flash Command Control register description (offset 0x90) */
#define FLASH_CMD_CTRL_EXECUTE_POS 0U
#define FLASH_CMD_CTRL_BUSY_POS 1U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_POS 7U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_MAX 31U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_BITS 5U
#define FLASH_CMD_CTRL_WRITE_BYTES_POS 12U
#define FLASH_CMD_CTRL_WRITE_BYTES_MAX 8U
#define FLASH_CMD_CTRL_WRITE_BYTES_BITS 3U
#define FLASH_CMD_CTRL_WRITE_ENABLE_POS 15U
#define FLASH_CMD_CTRL_ADDR_BYTES_POS 16U
#define FLASH_CMD_CTRL_ADDR_BYTES_MAX 4U
#define FLASH_CMD_CTRL_ADDR_BYTES_BITS 2U
#define FLASH_CMD_CTRL_ADDR_ENABLE_POS 19U
#define FLASH_CMD_CTRL_READ_BYTES_POS 20U
#define FLASH_CMD_CTRL_READ_BYTES_MAX 8U
#define FLASH_CMD_CTRL_READ_BYTES_BITS 3U
#define FLASH_CMD_CTRL_READ_ENABLE_POS 23U
#define FLASH_CMD_CTRL_OPCODE_POS 24U
/** Default register values of the QSPI Flash controller */
#define QSPI_CFG_REG_RESET_VALUE (0x80780081U)
#define DEVICE_READ_INSTR_REG_RESET_VALUE (0x00000003U)
#define DEVICE_WRITE_INSTR_REG_RESET_VALUE (0x00000002U)
#define DEVICE_SIZE_CFG_REG_RESET_VALUE (0x00101002U)
#define REMAP_ADDR_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_CONTROL_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_ADDRESS_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_WRITE_DATA_REG_RESET_VALUE (0x00000000U)
/**
* \brief Change specific bits in a 32 bits word.
*
* \param[in,out] word Pointer of the word to change
* \param[in] bits bits_length bits to put at bits_pos in the word
* pointed
* \param[in] bits_length Number of bits to change
* \param[in] bits_pos Position of the bits to change
*
* \note This function will do nothing if the parameters given are incorret:
* * word is NULL
* * bits_length + bits_pos > 32
* * bits_length is 0
*/
static void change_bits_in_word(volatile uint32_t *word,
uint32_t bits,
uint32_t bits_length,
uint32_t bits_pos)
{
uint32_t mask;
if ((word == NULL) ||
((bits_length + bits_pos) > BITS_PER_WORD) ||
(bits_length == 0U)) {
/* Silently fail */
return;
}
/* Change all the bits */
if (bits_length == BITS_PER_WORD) {
*word = bits;
return;
}
mask = ((1U << bits_length) - 1);
/*
* We change the bits in three steps:
* - clear bits_length bits with zeroes at bits_pos in the word
* - mask bits in case it contains more than bits_length bits
* - set the new bits in the cleared word
* Because the data pointed by word is only read once, the data will still
* be coherent after an interruption that changes it.
*/
*word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
}
/**
* \brief Configure reads or writes commands for direct operations.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Read/write opcode that will be used for every
* direct read/write
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering
* the command, this value must be between 0 and 31
* (both included)
* \param[in] is_reads_cfg true to configure direct reads, false to configure
* direct writes
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
static enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles,
bool is_reads_cfg)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Select the good register address if we want to configure reads or writes.
*/
volatile uint32_t *device_read_write_inst_reg = is_reads_cfg ?
&(reg_map->device_read_inst) :
&(reg_map->device_write_inst);
uint32_t device_read_write_inst_reg_copy = *device_read_write_inst_reg;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (dummy_cycles > DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&device_read_write_inst_reg_copy,
(uint32_t)opcode,
BITS_PER_BYTE,
DEVICE_READ_WRITE_INST_OPCODE_POS);
change_bits_in_word(&device_read_write_inst_reg_copy,
dummy_cycles,
DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS,
DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS);
*device_read_write_inst_reg = device_read_write_inst_reg_copy;
return QSPI_IP6514E_ERR_NONE;
}
/**
* \brief Given the public SPI mode enumeration, returns the private value it
* maps to in the register field.
*
* \param[in] spi_mode Read/write opcode that will be used for every direct
* read/write
*
* \return Return the correct DEVICE_READ_WRITE_INST_MODE value.
*/
static uint32_t spi_mode_field_value(enum qspi_ip6514e_spi_mode_t spi_mode)
{
switch (spi_mode) {
case QSPI_IP6514E_SPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_SPI;
case QSPI_IP6514E_DSPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_DSPI;
case QSPI_IP6514E_QSPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_QSPI;
default:
return ERROR_VALUE;
}
}
bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_IDLE_POS);
}
bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
struct qspi_ip6514e_dev_t* dev,
uint32_t div)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
/* div should be an even number. */
if (((div & 1U) == 1) ||
(div < QSPI_CFG_BAUD_DIV_MIN) ||
(div > QSPI_CFG_BAUD_DIV_MAX)) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/*
* The div value (between 2 and 32) needs to be stored in the register on a
* 4 bits field.
*/
change_bits_in_word(&(reg_map->qspi_cfg),
(div / 2) - 1,
QSPI_CFG_BAUD_DIV_BITS,
QSPI_CFG_BAUD_DIV_POS);
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
struct qspi_ip6514e_dev_t* dev,
enum qspi_ip6514e_spi_mode_t inst_type,
enum qspi_ip6514e_spi_mode_t addr_type,
enum qspi_ip6514e_spi_mode_t data_type)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
uint32_t inst_spi_mode, addr_spi_mode, data_spi_mode;
/*
* A local copy of the Device Read Instruction and Device Write Instruction
* registers is used to limit APB accesses.
*/
uint32_t device_read_inst_cpy = reg_map->device_read_inst;
uint32_t device_write_inst_cpy = reg_map->device_write_inst;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
/*
* First check that the instruction mode is not SPI. If that is the case,
* the address and data mode register fields become DO NOT CARE.
*/
inst_spi_mode = spi_mode_field_value(inst_type);
if (inst_spi_mode == ERROR_VALUE) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (inst_type != QSPI_IP6514E_SPI_MODE) {
change_bits_in_word(&(reg_map->device_read_inst),
inst_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_INST_INST_TYPE_POS);
return QSPI_IP6514E_ERR_NONE;
}
/* Now check and set address and data modes. */
addr_spi_mode = spi_mode_field_value(addr_type);
data_spi_mode = spi_mode_field_value(data_type);
if ((addr_spi_mode == ERROR_VALUE) || (data_spi_mode == ERROR_VALUE)) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* Change the Device Read Instruction register. */
change_bits_in_word(&device_read_inst_cpy,
inst_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_INST_INST_TYPE_POS);
change_bits_in_word(&device_read_inst_cpy,
addr_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
change_bits_in_word(&device_read_inst_cpy,
data_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
/* Change the Device Write Instruction register. */
change_bits_in_word(&device_write_inst_cpy,
addr_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
change_bits_in_word(&device_write_inst_cpy,
data_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
/* Save the changes. */
reg_map->device_read_inst = device_read_inst_cpy;
reg_map->device_write_inst = device_write_inst_cpy;
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles)
{
return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_READS);
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles)
{
return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_WRITES);
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
struct qspi_ip6514e_dev_t* dev,
uint32_t page_size)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (page_size > DEVICE_SIZE_PAGE_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&(reg_map->device_size),
page_size,
DEVICE_SIZE_PAGE_BYTES_BITS,
DEVICE_SIZE_PAGE_BYTES_POS);
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
struct qspi_ip6514e_dev_t* dev,
uint32_t bytes_number)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (bytes_number < DEVICE_SIZE_ADDR_BYTES_MIN ||
bytes_number > DEVICE_SIZE_ADDR_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&(reg_map->device_size),
bytes_number - 1,
DEVICE_SIZE_ADDR_BYTES_BITS,
DEVICE_SIZE_ADDR_BYTES_POS);
return QSPI_IP6514E_ERR_NONE;
}
void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Save the enable state to restore it after. */
bool is_enabled = qspi_ip6514e_is_enabled(dev);
if (is_enabled) {
qspi_ip6514e_disable(dev);
}
reg_map->remap_addr = offset;
SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
if (is_enabled) {
qspi_ip6514e_enable(dev);
}
}
void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Save the enable state to restore it after. */
bool is_enabled = qspi_ip6514e_is_enabled(dev);
if (is_enabled) {
qspi_ip6514e_disable(dev);
}
CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
if (is_enabled) {
qspi_ip6514e_enable(dev);
}
}
void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Restore the default value of the QSPI Configuration register. */
reg_map->qspi_cfg = QSPI_CFG_REG_RESET_VALUE;
/* Restore the default value of the Device R/W Instruction registers. */
reg_map->device_read_inst = DEVICE_READ_INSTR_REG_RESET_VALUE;
reg_map->device_write_inst = DEVICE_WRITE_INSTR_REG_RESET_VALUE;
/* Restore the default value of the Device Size Configuration register. */
reg_map->device_size = DEVICE_SIZE_CFG_REG_RESET_VALUE;
/* Restore the default value of the Remap Address register. */
reg_map->remap_addr = REMAP_ADDR_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Control register. */
reg_map->flash_cmd_ctrl = FLASH_CMD_CONTROL_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Address register. */
reg_map->flash_cmd_addr = FLASH_CMD_ADDRESS_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Write Data registers. */
reg_map->flash_cmd_write_data_lower = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
reg_map->flash_cmd_write_data_upper = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
/*
* This function does not affect the Flash Command Read Data registers
* which are completely Read-Only.
*/
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* To limit APB accesses, we set this reg up locally before */
uint32_t flash_cmd_ctrl = 0U;
bool read_requested = ((read_data != NULL) && (read_len != 0));
bool write_requested = ((write_data != NULL) && (write_len != 0));
bool addr_requested = (addr_bytes_number != 0);
/*
* To prevent unaligned and byte or halfbyte accesses to the APB registers,
* a word aligned buffer is used to temporary transfer the data before doing
* word accesses on these registers from that buffer.
*/
uint32_t data_regs[DATA_REG_NUMBER] = {0};
if (read_len > FLASH_CMD_CTRL_READ_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (write_len > FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (addr_bytes_number > FLASH_CMD_CTRL_ADDR_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (dummy_cycles > FLASH_CMD_CTRL_DUMMY_CYCLES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (read_requested && write_requested) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&flash_cmd_ctrl,
(uint32_t)opcode,
BITS_PER_BYTE,
FLASH_CMD_CTRL_OPCODE_POS);
/* Enable read if requested */
if (read_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_READ_ENABLE_POS);
change_bits_in_word(&flash_cmd_ctrl,
read_len - 1,
FLASH_CMD_CTRL_READ_BYTES_BITS,
FLASH_CMD_CTRL_READ_BYTES_POS);
}
/* Enable write if requested */
if (write_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_WRITE_ENABLE_POS);
change_bits_in_word(&flash_cmd_ctrl,
write_len - 1,
FLASH_CMD_CTRL_WRITE_BYTES_BITS,
FLASH_CMD_CTRL_WRITE_BYTES_POS);
if (IS_ADDR_ALIGNED(write_data) && IS_ADDR_ALIGNED(write_len)) {
/*
* Optimised case when write_data is word aligned and write_len is
* 4 or 8.
*/
reg_map->flash_cmd_write_data_lower = *(uint32_t *)write_data;
if (write_len == FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
reg_map->flash_cmd_write_data_upper =
*((uint32_t *)write_data + 1);
}
} else {
/*
* data_regs is used as a buffer to only do unaligned access on the
* AHB bus and word aligned accesses to the APB registers.
*/
memcpy((void *)data_regs, write_data, write_len);
/*
* Only write_len bytes will be written even if both data registers
* are written.
*/
reg_map->flash_cmd_write_data_lower = data_regs[DATA_REG_LOWER];
reg_map->flash_cmd_write_data_upper = data_regs[DATA_REG_UPPER];
}
}
/* Enable the address if requested */
if (addr_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_ADDR_ENABLE_POS);
reg_map->flash_cmd_addr = addr;
change_bits_in_word(&flash_cmd_ctrl,
addr_bytes_number - 1,
FLASH_CMD_CTRL_ADDR_BYTES_BITS,
FLASH_CMD_CTRL_ADDR_BYTES_POS);
}
/* Put dummy cycles number */
change_bits_in_word(&flash_cmd_ctrl,
dummy_cycles,
FLASH_CMD_CTRL_DUMMY_CYCLES_BITS,
FLASH_CMD_CTRL_DUMMY_CYCLES_POS);
/* Copy the Flash Command Control register and execute the command */
reg_map->flash_cmd_ctrl = flash_cmd_ctrl;
SET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_EXECUTE_POS);
/* Wait for termination */
while (GET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_BUSY_POS));
/*
* Recolt the read data if it was requested. read_len validity has already
* been verified at this point.
*/
if (read_requested) {
if (IS_ADDR_ALIGNED(read_data) && IS_ADDR_ALIGNED(read_len)) {
/*
* Optimised case when read_data is word aligned and read_len is
* 4 or 8.
*/
*(uint32_t *)read_data = reg_map->flash_cmd_read_data_lower;
if (read_len == FLASH_CMD_CTRL_READ_BYTES_MAX) {
*((uint32_t *)read_data + 1) =
reg_map->flash_cmd_read_data_upper;
}
} else {
/*
* Only read_len bytes have been written even if both data registers
* are written.
*/
data_regs[DATA_REG_LOWER] = reg_map->flash_cmd_read_data_lower;
data_regs[DATA_REG_UPPER] = reg_map->flash_cmd_read_data_upper;
/*
* data_regs is used as a buffer to only do unaligned access on the
* AHB bus and word aligned accesses to the APB registers.
*/
memcpy(read_data, (void *)data_regs, read_len);
}
}
return QSPI_IP6514E_ERR_NONE;
}
void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode)
{
/*
* No read/write data, no address, no dummy cycles.
* Given the arguments, this function can not fail.
*/
(void)qspi_ip6514e_send_cmd(dev,
opcode,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_NOT_USED,
ARG_NOT_USED,
0);
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
/* Read arguments are expected */
if (read_data == ARG_PTR_NOT_USED || read_len == ARG_NOT_USED) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* No write data */
return qspi_ip6514e_send_cmd(dev,
opcode,
read_data,
read_len,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
addr,
addr_bytes_number,
dummy_cycles);
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
/* Write arguments are expected */
if (write_data == ARG_PTR_NOT_USED || write_len == ARG_NOT_USED) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* No read data, no dummy cycles */
return qspi_ip6514e_send_cmd(dev,
opcode,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
write_data,
write_len,
addr,
addr_bytes_number,
dummy_cycles);
}

View File

@ -1,418 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file qspi_ip6514e_drv.h
* \brief Driver for Cadence QSPI Flash Controller IP.
* There are two ways to communicate with the flash memory device:
* - issue AHB requests for direct read and writes in the Flash memory
* mapped address zone. The commands used for those can be configured
* by the driver
* - send a command to the device to access his internal registers and
* do other operations like erasing a sector
* At reset, the QSPI controller will work in a default mode which will
* allow to do basic commands. It should be configured with the
* flash memory device specifications for optimal use for commands and
* direct reads/writes. Here is an example of configuration:
* - send command to activate QSPI mode on the flash memory device
* - send command to change dummy cycles on the flash memory device
* - check if any operation is ungoing
* - disable the QSPI controller
* - change the baud rate divisor
* - activate the QSPI mode on the controller
* - change the dummy cycles number and opcode for reads/writes
* - change the number of bytes per page
* - change the number of address bytes
* - activate the QSPI controller
*
* Warning: none of the functions declared here check if the dev
* argument points to NULL.
*/
#ifndef __QSPI_IP6514E_DRV_H__
#define __QSPI_IP6514E_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Cadence QSPI IP6514E error enumeration types
*/
enum qspi_ip6514e_error_t {
QSPI_IP6514E_ERR_NONE,
QSPI_IP6514E_ERR_WRONG_ARGUMENT,
QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
QSPI_IP6514E_ERR_READ_IN_PROGRESS,
QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
/* Any new error should be added to the enumeration type error of
* the corresponding Flash device library as well.
*/
};
/**
* \brief Cadence QSPI IP6514E SPI modes
*/
enum qspi_ip6514e_spi_mode_t {
QSPI_IP6514E_SPI_MODE,
/*!< Use 1 line for Instruction, Address and Data */
QSPI_IP6514E_DSPI_MODE,
/*!< Use 2 lines for Instruction, Address and Data */
QSPI_IP6514E_QSPI_MODE,
/*!< Use 4 lines for Instruction, Address and Data */
};
/**
* \brief Cadence QSPI IP6514E device configuration structure
*/
struct qspi_ip6514e_dev_cfg_t {
const uint32_t base; /*!< QSPI IP6514E base address */
/*
* If not all the AHB wires are connected to the QSPI Flash Controller the
* driver can still access all of the Flash memory. The bits of this value
* should be put to 1 for every wire that is connected. Set it to
* 0xFFFFFFFFU if all AHB address wires are connected to the
* QSPI Flash Controller.
*/
uint32_t addr_mask;
};
/**
* \brief Cadence QSPI IP6514E device structure
*/
struct qspi_ip6514e_dev_t {
const struct qspi_ip6514e_dev_cfg_t* const cfg;
/*!< QSPI IP6514E configuration */
};
/**
* \brief Check if the controller is idle.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \return true if the controller is idle, false otherwise.
*/
bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Check if the controller is enabled.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \return true if the controller is enabled, false otherwise.
*/
bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Disable the QSPI controller.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*/
void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Enable the QSPI controller.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*/
void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Change the baud rate divisor.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] div Baud rate divisor value. It can only be an even number
* between 2 and 32 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI frequency is calculated dividing the QSPI controller clock by
* this divisor. Please check Flash memory device specifications to know
* the maximal frequency that can be used.
* \note The QSPI controller should be disabled before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
struct qspi_ip6514e_dev_t* dev,
uint32_t div);
/**
* \brief Set SPI mode for instruction, address and data.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] inst_type SPI mode to use for the instruction part of the command
* \param[in] addr_type SPI mode to use for the address part of the command
* \param[in] data_type SPI mode to use for the data part of the command
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note Changing this setting will affect commands and direct operations.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
struct qspi_ip6514e_dev_t* dev,
enum qspi_ip6514e_spi_mode_t inst_type,
enum qspi_ip6514e_spi_mode_t addr_type,
enum qspi_ip6514e_spi_mode_t data_type);
/**
* \brief Configure read commands for direct reads.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Read opcode that will be used for every direct read
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
* command, this value must be between 0 and 31
* (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles);
/**
* \brief Configure write commands for direct writes.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Write opcode that will be used for every direct write
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
* command, this value must be between 0 and 31
* (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles);
/**
* \brief Change the number of bytes per device page.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] page_size Number of bytes per device page, must be between 0
* and 4095 (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note This function will affect direct reads/writes.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
struct qspi_ip6514e_dev_t* dev,
uint32_t page_size);
/**
* \brief Change the number of device address bytes.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] bytes_number Number of device address bytes, must be between 1
* and 16 (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note This function will affect direct reads/writes.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
struct qspi_ip6514e_dev_t* dev,
uint32_t bytes_number);
/**
* \brief Remap the incoming AHB address with an offset for direct accesses.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] offset Offset that will be added to the incoming AHB address to
* access the Flash memory
*
* \note This function will only affect direct reads/writes.
* \note This function does not check if the resulting address is out of memory
* bounds.
*/
void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset);
/**
* \brief Disable AHB address remapping for direct accesses.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \note This function will disable the controller if it is not already
* disabled and enable it again (if it was).
* \note This function will only affect direct reads/writes.
*/
void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Restore the default value of the QSPI controller registers.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \note The QSPI controller should be disabled before calling this function.
*/
void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Send a command to the flash memory device using the Software Triggered
* Instruction Generator (STIG).
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[out] read_data Pointer to a memory zone where the read_len
* bytes read will be written to. If no data is to
* be read for the command,
* this argument should be NULL.
* \param[in] read_len Number of bytes to read for the command. If
* no bytes are to be read, use 0 for argument
* otherwise between 1 and 8 bytes (both
* included) can be read.
* \param[in] write_data Pointer to a memory zone where are
* located the write_len bytes to write for
* this command. If no bytes are to be written,
* use NULL as argument.
* \param[in] write_len Number of bytes to write for the command. If
* no bytes are to be written, use 0 for
* argument otherwise between 1 and 8 bytes
* (both included) can be written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
/**
* \brief Send a simple command to the flash memory device using the Software
* Triggered Instruction Generator (STIG) with no data arguments.
* This command can be used for example to send the WRITE ENABLE command.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode);
/**
* \brief Send a read command to the flash memory device using the Software
* Triggered Instruction Generator (STIG). This command can be used to
* read Flash memory data or registers.
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[out] read_data Pointer to a memory zone where the
* read_len bytes read will be written to.
* \param[in] read_len Number of bytes to read for the command.
* Between 1 and 8 bytes (both included) can be
* read.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
/**
* \brief Send a write command to the flash memory device using the Software
* Triggered Instruction Generator (STIG). This command can be used to
* write Flash memory or registers.
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[in] write_data Pointer to a memory zone where are
* located the write_len bytes to write for
* this command.
* \param[in] write_len Number of bytes to write for the command.
* Between 1 and 8 bytes (both included) can be
* written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
#ifdef __cplusplus
}
#endif
#endif /* __QSPI_IP6514E_DRV_H__ */

View File

@ -1,132 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device.h"
#include "flash_layout.h"
#include "flash_api.h"
#if DEVICE_FLASH
#define FLASH_DEV MT25QL_DEV_NS
int32_t flash_init(flash_t *obj)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
qspi_ip6514e_enable(FLASH_DEV.controller);
/* Configure QSPI Flash controller to operate in single SPI mode and
* to use fast Flash commands */
err = mt25ql_config_mode(&FLASH_DEV, MT25QL_FUNC_STATE_FAST);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_free(flash_t *obj)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
/* Restores the QSPI Flash controller and MT25QL to default state */
err = mt25ql_restore_default_state(&FLASH_DEV);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
err = mt25ql_erase(&FLASH_DEV, address, MT25QL_ERASE_SUBSECTOR_4K);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_read(flash_t *obj, uint32_t address,
uint8_t *data, uint32_t size)
{
(void)obj;
enum mt25ql_error_t err = MT25QL_ERR_NONE;
err = mt25ql_command_read(&FLASH_DEV, address, data, size);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
err = mt25ql_command_write(&FLASH_DEV, address, data, size);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
{
(void)(obj);
if ((address >= NS_QSPI_ALIAS_BASE) && (address < NS_QSPI_ALIAS_BASE + FLASH_TOTAL_SIZE)) {
return SUBSECTOR_4KB;
}
return MBED_FLASH_INVALID_SIZE;
}
uint32_t flash_get_page_size(const flash_t *obj)
{
(void)(obj);
return FLASH_PAGE_SIZE;
}
uint32_t flash_get_start_address(const flash_t *obj)
{
(void)(obj);
return NS_QSPI_ALIAS_BASE;
}
uint32_t flash_get_size(const flash_t *obj)
{
(void)(obj);
return FLASH_TOTAL_SIZE;
}
uint8_t flash_get_erase_value(const flash_t *obj)
{
(void)obj;
return 0xFF;
}
#endif // DEVICE_FLASH

View File

@ -1,324 +0,0 @@
/*
* Copyright (c) 2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdio.h>
#include "platform/include/tfm_spm_hal.h"
#include "spm_api.h"
#include "spm_db.h"
#include "tfm_platform_core_api.h"
#include "target_cfg.h"
#include "Driver_MPC.h"
#include "mpu_armv8m_drv.h"
#include "region_defs.h"
#include "secure_utilities.h"
/* Import MPC driver */
extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC;
/* Get address of memory regions to configure MPU */
extern const struct memory_region_limits memory_regions;
struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
void tfm_spm_hal_init_isolation_hw(void)
{
/* Configures non-secure memory spaces in the target */
sau_and_idau_cfg();
mpc_init_cfg();
ppc_init_cfg();
}
void tfm_spm_hal_configure_default_isolation(
const struct tfm_spm_partition_platform_data_t *platform_data)
{
if (platform_data) {
if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
ppc_configure_to_secure(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
}
}
#if TFM_LVL != 1
#define MPU_REGION_VENEERS 0
#define MPU_REGION_TFM_UNPRIV_CODE 1
#define MPU_REGION_TFM_UNPRIV_DATA 2
#define MPU_REGION_NS_DATA 3
#define PARTITION_REGION_RO 4
#define PARTITION_REGION_RW_STACK 5
#define PARTITION_REGION_PERIPH 6
#define PARTITION_REGION_SHARE 7
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
static enum spm_err_t tfm_spm_mpu_init(void)
{
struct mpu_armv8m_region_cfg_t region_cfg;
mpu_armv8m_clean(&dev_mpu_s);
/* Veneer region */
region_cfg.region_nr = MPU_REGION_VENEERS;
region_cfg.region_base = memory_regions.veneer_base;
region_cfg.region_limit = memory_regions.veneer_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged code region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;
region_cfg.region_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
region_cfg.region_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged data region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;
region_cfg.region_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);
region_cfg.region_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged non-secure data region */
region_cfg.region_nr = MPU_REGION_NS_DATA;
region_cfg.region_base = NS_DATA_START;
region_cfg.region_limit = NS_DATA_LIMIT;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
enum spm_err_t tfm_spm_hal_partition_sandbox_config(
const struct tfm_spm_partition_memory_data_t *memory_data,
const struct tfm_spm_partition_platform_data_t *platform_data)
{
/* This function takes a partition id and enables the
* SPM partition for that partition
*/
struct mpu_armv8m_region_cfg_t region_cfg;
mpu_armv8m_disable(&dev_mpu_s);
/* Configure Regions */
if (memory_data->ro_start) {
/* RO region */
region_cfg.region_nr = PARTITION_REGION_RO;
region_cfg.region_base = memory_data->ro_start;
region_cfg.region_limit = memory_data->ro_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
!= MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
}
/* RW, ZI and stack as one region */
region_cfg.region_nr = PARTITION_REGION_RW_STACK;
region_cfg.region_base = memory_data->rw_start;
region_cfg.region_limit = memory_data->stack_top;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
if (platform_data) {
/* Peripheral */
region_cfg.region_nr = PARTITION_REGION_PERIPH;
region_cfg.region_base = platform_data->periph_start;
region_cfg.region_limit = platform_data->periph_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
!= MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
ppc_en_secure_unpriv(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(
const struct tfm_spm_partition_memory_data_t *memory_data,
const struct tfm_spm_partition_platform_data_t *platform_data)
{
/* This function takes a partition id and disables the
* SPM partition for that partition
*/
if (platform_data) {
/* Peripheral */
ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
mpu_armv8m_disable(&dev_mpu_s);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
/**
* Set share region to which the partition needs access
*/
enum spm_err_t tfm_spm_hal_set_share_region(
enum tfm_buffer_share_region_e share)
{
struct mpu_armv8m_region_cfg_t region_cfg;
enum spm_err_t res = SPM_ERR_INVALID_CONFIG;
uint32_t scratch_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
uint32_t scratch_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
mpu_armv8m_disable(&dev_mpu_s);
if (share == TFM_BUFFER_SHARE_DISABLE) {
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);
} else {
region_cfg.region_nr = PARTITION_REGION_SHARE;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
switch (share) {
case TFM_BUFFER_SHARE_SCRATCH:
/* Use scratch area for SP-to-SP data sharing */
region_cfg.region_base = scratch_base;
region_cfg.region_limit = scratch_limit;
res = SPM_ERR_OK;
break;
case TFM_BUFFER_SHARE_NS_CODE:
region_cfg.region_base = memory_regions.non_secure_partition_base;
region_cfg.region_limit = memory_regions.non_secure_partition_limit;
/* Only allow read access to NS code region and keep
* exec.never attribute
*/
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
res = SPM_ERR_OK;
break;
default:
/* Leave res to be set to SPM_ERR_INVALID_CONFIG */
break;
}
if (res == SPM_ERR_OK) {
mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg);
}
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return res;
}
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
{
#if TFM_LVL != 1
if (tfm_spm_mpu_init() != SPM_ERR_OK) {
ERROR_MSG("Failed to set up initial MPU configuration! Halting.");
while (1) {
;
}
}
#endif
}
void MPC_Handler(void)
{
/* Clear MPC interrupt flag and pending MPC IRQ */
Driver_CODE_SRAM_MPC.ClearInterrupt();
NVIC_ClearPendingIRQ(S_MPC_COMBINED_IRQn);
/* Print fault message and block execution */
LOG_MSG("Oops... MPC fault!!!");
/* Inform TF-M core that isolation boundary has been violated */
tfm_access_violation_handler();
}
void PPC_Handler(void)
{
/*
* Due to an issue on the FVP, the PPC fault doesn't trigger a
* PPC IRQ which is handled by the PPC_handler.
* In the FVP execution, this code is not execute.
*/
/* Clear PPC interrupt flag and pending PPC IRQ */
ppc_clear_irq();
NVIC_ClearPendingIRQ(S_PPC_COMBINED_IRQn);
/* Print fault message*/
LOG_MSG("Oops... PPC fault!!!");
/* Inform TF-M core that isolation boundary has been violated */
tfm_access_violation_handler();
}
uint32_t tfm_spm_hal_get_ns_VTOR(void)
{
return memory_regions.non_secure_code_start;
}
uint32_t tfm_spm_hal_get_ns_MSP(void)
{
return *((uint32_t *)memory_regions.non_secure_code_start);
}
uint32_t tfm_spm_hal_get_ns_entry_point(void)
{
return *((uint32_t *)(memory_regions.non_secure_code_start+ 4));
}

View File

@ -1,370 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cmsis.h"
#include "target_cfg.h"
#include "Driver_MPC.h"
#include "platform_retarget_dev.h"
#include "region_defs.h"
#include "tfm_secure_api.h"
/* Macros to pick linker symbols */
#define REGION(a, b, c) a##b##c
#define REGION_NAME(a, b, c) REGION(a, b, c)
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
/* The section names come from the scatter file */
REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base);
REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Base);
REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Limit);
const struct memory_region_limits memory_regions = {
.non_secure_code_start =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
BL2_HEADER_SIZE,
.non_secure_partition_base =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
.non_secure_partition_limit =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
NS_PARTITION_SIZE - 1,
.veneer_base =
(uint32_t)&REGION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Base),
.veneer_limit =
(uint32_t)&REGION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Limit),
};
/* Allows software, via SAU, to define the code region as a NSC */
#define NSCCFG_CODENSC 1
/* Import MPC driver */
extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC, Driver_QSPI_MPC;
extern ARM_DRIVER_MPC Driver_ISRAM0_MPC, Driver_ISRAM1_MPC;
extern ARM_DRIVER_MPC Driver_ISRAM2_MPC, Driver_ISRAM3_MPC;
/* Define Peripherals NS address range for the platform */
#define PERIPHERALS_BASE_NS_START (0x40000000)
#define PERIPHERALS_BASE_NS_END (0x4FFFFFFF)
/* Enable system reset request for CPU 0 */
#define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 4U)
/* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field,
* otherwise the processor ignores the write.
*/
#define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos))
/* Debug configuration flags */
#define SPNIDEN_SEL_STATUS (0x01u << 7)
#define SPNIDEN_STATUS (0x01u << 6)
#define SPIDEN_SEL_STATUS (0x01u << 5)
#define SPIDEN_STATUS (0x01u << 4)
#define NIDEN_SEL_STATUS (0x01u << 3)
#define NIDEN_STATUS (0x01u << 2)
#define DBGEN_SEL_STATUS (0x01u << 1)
#define DBGEN_STATUS (0x01u << 0)
#define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \
NIDEN_SEL_STATUS | DBGEN_SEL_STATUS)
struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart = {
MUSCA_UART1_NS_BASE,
MUSCA_UART1_NS_BASE + 0xFFF,
PPC_SP_DO_NOT_CONFIGURE,
-1
};
void enable_fault_handlers(void)
{
/* Enables BUS, MEM, USG and Secure faults */
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
| SCB_SHCSR_BUSFAULTENA_Msk
| SCB_SHCSR_MEMFAULTENA_Msk
| SCB_SHCSR_SECUREFAULTENA_Msk;
}
void system_reset_cfg(void)
{
struct sysctrl_t *sysctrl = (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
uint32_t reg_value = SCB->AIRCR;
/* Enable system reset request for CPU 0, to be triggered via
* NVIC_SystemReset function.
*/
sysctrl->resetmask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST;
/* Clear SCB_AIRCR_VECTKEY value */
reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk);
/* Enable system reset request only to the secure world */
reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk);
SCB->AIRCR = reg_value;
}
void tfm_spm_hal_init_debug(void)
{
volatile struct sysctrl_t *sys_ctrl =
(struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
#if defined(DAUTH_NONE)
/* Set all the debug enable selector bits to 1 */
sys_ctrl->secdbgset = All_SEL_STATUS;
/* Set all the debug enable bits to 0 */
sys_ctrl->secdbgclr =
DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS;
#elif defined(DAUTH_NS_ONLY)
/* Set all the debug enable selector bits to 1 */
sys_ctrl->secdbgset = All_SEL_STATUS;
/* Set the debug enable bits to 1 for NS, and 0 for S mode */
sys_ctrl->secdbgset = DBGEN_STATUS | NIDEN_STATUS;
sys_ctrl->secdbgclr = SPIDEN_STATUS | SPNIDEN_STATUS;
#elif defined(DAUTH_FULL)
/* Set all the debug enable selector bits to 1 */
sys_ctrl->secdbgset = All_SEL_STATUS;
/* Set all the debug enable bits to 1 */
sys_ctrl->secdbgset =
DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS;
#else
#if !defined(DAUTH_CHIP_DEFAULT)
#error "No debug authentication setting is provided."
#endif
/* Set all the debug enable selector bits to 0 */
sys_ctrl->secdbgclr = All_SEL_STATUS;
/* No need to set any enable bits because the value depends on
* input signals.
*/
#endif
}
/*----------------- NVIC interrupt target state to NS configuration ----------*/
void nvic_interrupt_target_state_cfg()
{
/* Target every interrupt to NS; unimplemented interrupts will be WI */
for (uint8_t i=0; i<sizeof(NVIC->ITNS)/sizeof(NVIC->ITNS[0]); i++) {
NVIC->ITNS[i] = 0xFFFFFFFF;
}
/* Make sure that MPC and PPC are targeted to S state */
NVIC_ClearTargetState(S_MPC_COMBINED_IRQn);
NVIC_ClearTargetState(S_PPC_COMBINED_IRQn);
}
/*----------------- NVIC interrupt enabling for S peripherals ----------------*/
void nvic_interrupt_enable()
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
/* MPC interrupt enabling */
Driver_QSPI_MPC.EnableInterrupt();
Driver_CODE_SRAM_MPC.EnableInterrupt();
NVIC_EnableIRQ(S_MPC_COMBINED_IRQn);
/* PPC interrupt enabling */
/* Clear pending PPC interrupts */
/* In the PPC configuration function, we have used the Non-Secure
* Privilege Control Block to grant unprivilged NS access to some
* peripherals used by NS. That triggers a PPC0 exception as that
* register is meant for NS privileged access only. Clear it here
*/
spctrl->secppcintclr = CMSDK_APB_PPC0_INT_POS_MASK;
/* Enable PPC interrupts for APB PPC */
spctrl->secppcinten |= CMSDK_APB_PPC0_INT_POS_MASK;
spctrl->secppcinten |= CMSDK_APB_PPC1_INT_POS_MASK;
spctrl->secppcinten |= CMSDK_APB_PPCEXP0_INT_POS_MASK;
spctrl->secppcinten |= CMSDK_APB_PPCEXP1_INT_POS_MASK;
spctrl->secppcinten |= CMSDK_APB_PPCEXP2_INT_POS_MASK;
spctrl->secppcinten |= CMSDK_APB_PPCEXP3_INT_POS_MASK;
NVIC_EnableIRQ(S_PPC_COMBINED_IRQn);
}
/*------------------- SAU/IDAU configuration functions -----------------------*/
void sau_and_idau_cfg(void)
{
/* Enables SAU */
TZ_SAU_Enable();
/* Configures SAU regions to be non-secure */
SAU->RNR = TFM_NS_REGION_CODE;
SAU->RBAR = (memory_regions.non_secure_partition_base
& SAU_RBAR_BADDR_Msk);
SAU->RLAR = (memory_regions.non_secure_partition_limit
& SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
SAU->RNR = TFM_NS_REGION_DATA;
SAU->RBAR = (NS_DATA_START & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (NS_DATA_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
/* Configures veneers region to be non-secure callable */
SAU->RNR = TFM_NS_REGION_VENEER;
SAU->RBAR = (memory_regions.veneer_base & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (memory_regions.veneer_limit & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk
| SAU_RLAR_NSC_Msk;
/* Configure the peripherals space */
SAU->RNR = TFM_NS_REGION_PERIPH_1;
SAU->RBAR = (PERIPHERALS_BASE_NS_START & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
/* FIXME: Secondary image partition info comes from BL2. Configure SAU
* based on those limits.
*/
/* Allows SAU to define the code region as a NSC */
struct spctrl_def* spctrl = CMSDK_SPCTRL;
spctrl->nsccfg |= NSCCFG_CODENSC;
}
/*------------------- Memory configuration functions -------------------------*/
void mpc_init_cfg(void)
{
ARM_DRIVER_MPC* mpc_data_region0 = &Driver_ISRAM0_MPC;
ARM_DRIVER_MPC* mpc_data_region1 = &Driver_ISRAM1_MPC;
ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
Driver_CODE_SRAM_MPC.Initialize();
Driver_CODE_SRAM_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
memory_regions.non_secure_partition_limit,
ARM_MPC_ATTR_NONSECURE);
mpc_data_region0->Initialize();
mpc_data_region0->ConfigRegion(MPC_ISRAM0_RANGE_BASE_S,
MPC_ISRAM0_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
mpc_data_region1->Initialize();
mpc_data_region1->ConfigRegion(MPC_ISRAM1_RANGE_BASE_S,
MPC_ISRAM1_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
mpc_data_region2->Initialize();
#if defined(TEST_FRAMEWORK_S) || defined(TEST_FRAMEWORK_NS)
/* To run the regression tests on Musca A1, it is required to assign more
* RAM memory in the secure execution environment.
* So, the secure RAM memory size is 96KB and the non-secure one is 32 KB.
* When it is not required to run the regression tests, the RAM memory
* partition is the original one which is 64KB of the RAM memory for each
* execution environment.
*/
mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_S,
MPC_ISRAM2_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
#else
mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_NS,
MPC_ISRAM2_RANGE_LIMIT_NS,
ARM_MPC_ATTR_NONSECURE);
#endif
mpc_data_region3->Initialize();
mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_NS,
MPC_ISRAM3_RANGE_LIMIT_NS,
ARM_MPC_ATTR_NONSECURE);
/* Lock down the MPC configuration */
Driver_CODE_SRAM_MPC.LockDown();
mpc_data_region0->LockDown();
mpc_data_region1->LockDown();
mpc_data_region2->LockDown();
mpc_data_region3->LockDown();
/* Add barriers to assure the MPC configuration is done before continue
* the execution.
*/
__DSB();
__ISB();
}
/*---------------------- PPC configuration functions -------------------------*/
void ppc_init_cfg(void)
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
struct nspctrl_def* nspctrl = CMSDK_NSPCTRL;
/* Grant non-secure access to peripherals in the PPC0
* (timer0 and 1, dualtimer, watchdog, mhu 0 and 1)
*/
spctrl->apbnsppc0 |= (1U << CMSDK_TIMER0_APB_PPC_POS);
spctrl->apbnsppc0 |= (1U << CMSDK_TIMER1_APB_PPC_POS);
spctrl->apbnsppc0 |= (1U << CMSDK_DTIMER_APB_PPC_POS);
spctrl->apbnsppc0 |= (1U << CMSDK_MHU0_APB_PPC_POS);
spctrl->apbnsppc0 |= (1U << CMSDK_MHU1_APB_PPC_POS);
/* Grant non-secure access to S32K Timer in PPC1*/
spctrl->apbnsppc1 |= (1U << CMSDK_S32K_TIMER_PPC_POS);
/* Grant non-secure access for AHB peripherals on EXP0 */
spctrl->ahbnsppcexp0 = (1U << MUSCA_PERIPHS_AHB_PPC_POS);
/* in NS, grant un-privileged for AHB peripherals on EXP0 */
nspctrl->ahbnspppcexp0 = (1U << MUSCA_PERIPHS_AHB_PPC_POS);
/* Configure the response to a security violation as a
* bus error instead of RAZ/WI
*/
spctrl->secrespcfg |= 1U;
}
void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
{
/* Setting NS flag for peripheral to enable NS access */
struct spctrl_def* spctrl = CMSDK_SPCTRL;
((uint32_t*)&(spctrl->ahbnsppc0))[bank] |= (1U << pos);
}
void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
{
/* Clear NS flag for peripheral to prevent NS access */
struct spctrl_def* spctrl = CMSDK_SPCTRL;
((uint32_t*)&(spctrl->ahbnsppc0))[bank] &= ~(1U << pos);
}
void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
((uint32_t*)&(spctrl->ahbspppc0))[bank] |= (1U << pos);
}
void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
((uint32_t*)&(spctrl->ahbspppc0))[bank] &= ~(1U << pos);
}
void ppc_clear_irq(void)
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
/* Clear APB PPC EXP2 IRQ */
spctrl->secppcintclr = CMSDK_APB_PPCEXP2_INT_POS_MASK;
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2018-2019 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __TARGET_CFG_H__
#define __TARGET_CFG_H__
#include "tfm_peripherals_def.h"
/**
* \brief Defines the word offsets of Slave Peripheral Protection Controller
* Registers
*/
enum ppc_bank_e
{
PPC_SP_DO_NOT_CONFIGURE = -1,
PPC_SP_AHB_PPC0 = 0,
PPC_SP_RES0,
PPC_SP_RES1,
PPC_SP_RES2,
PPC_SP_AHB_PPC_EXP0,
PPC_SP_AHB_PPC_EXP1,
PPC_SP_AHB_PPC_EXP2,
PPC_SP_AHB_PPC_EXP3,
PPC_SP_APB_PPC0,
PPC_SP_APB_PPC1,
PPC_SP_RES3,
PPC_SP_RES4,
PPC_SP_APB_PPC_EXP0,
PPC_SP_APB_PPC_EXP1,
PPC_SP_APB_PPC_EXP2,
PPC_SP_APB_PPC_EXP3,
};
/**
* \brief Store the addresses of memory regions
*/
struct memory_region_limits {
uint32_t non_secure_code_start;
uint32_t non_secure_partition_base;
uint32_t non_secure_partition_limit;
uint32_t veneer_base;
uint32_t veneer_limit;
};
/**
* \brief Holds the data necessary to do isolation for a specific peripheral.
*/
struct tfm_spm_partition_platform_data_t
{
uint32_t periph_start;
uint32_t periph_limit;
int16_t periph_ppc_bank;
int16_t periph_ppc_loc;
};
/**
* \brief Configures the Memory Protection Controller.
*/
void mpc_init_cfg(void);
/**
* \brief Configures the Peripheral Protection Controller.
*/
void ppc_init_cfg(void);
/**
* \brief Restict access to peripheral to secure
*/
void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc);
/**
* \brief Allow non-secure access to peripheral
*/
void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc);
/**
* \brief Enable secure unprivileged access to peripheral
*/
void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
/**
* \brief Clear secure unprivileged access to peripheral
*/
void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
/**
* \brief Clears PPC interrupt.
*/
void ppc_clear_irq(void);
/**
* \brief Configures SAU and IDAU.
*/
void sau_and_idau_cfg(void);
#endif /* __TARGET_CFG_H__ */

View File

@ -1,17 +0,0 @@
/*
* Copyright (c) 2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __TFM_PERIPHERALS_DEF_H__
#define __TFM_PERIPHERALS_DEF_H__
struct tfm_spm_partition_platform_data_t;
extern struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart;
#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart)
#endif /* __TFM_PERIPHERALS_DEF_H__ */

View File

@ -18,7 +18,7 @@
* limitations under the License.
*/
#include "../../../partition/region_defs.h"
#include "../../partition/region_defs.h"
#include "../cmsis_nvic.h"
#if !defined(MBED_ROM_START)

View File

@ -22,7 +22,7 @@
/* Linker script to configure memory regions. */
/* This file will be run trough the pre-processor. */
#include "../../../partition/region_defs.h"
#include "../../partition/region_defs.h"
#include "../cmsis_nvic.h"
/* Stack size is 1K for Mbed-OS */

View File

@ -24,7 +24,7 @@
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#include "../../partition/region_defs.h"
#include "../partition/region_defs.h"
#define NVIC_NUM_VECTORS (16 + 76)
/** Location of vectors to move in RAM */

View File

@ -30,91 +30,28 @@
*/
/* ARM SCC */
#if defined(TARGET_MUSCA_A1_S)
#define MUSCA_A1_SCC_S
#endif
#if defined(TARGET_MUSCA_A1_NS)
#define MUSCA_A1_SCC_NS
#define MUSCA_A1_SCC_DEV MUSCA_A1_SCC_DEV_NS
#endif
#if defined(TARGET_MUSCA_A1_S)
/* ARM Memory Protection Controller (MPC) SIE 200 */
#define MPC_ISRAM0_S
#define MPC_ISRAM1_S
#define MPC_ISRAM2_S
#define MPC_ISRAM3_S
#define MPC_CODE_SRAM_S
#define MPC_CODE_SRAM_NS
#define MPC_QSPI_S
#define MPC_QSPI_NS
/* ARM Peripheral Protection Controllers (PPC) */
#define AHB_PPC0_S
#define AHB_PPCEXP0_S
#define AHB_PPCEXP1_S
#define AHB_PPCEXP2_S
#define AHB_PPCEXP3_S
#define APB_PPC0_S
#define APB_PPC1_S
#define APB_PPCEXP0_S
#define APB_PPCEXP1_S
#define APB_PPCEXP2_S
#define APB_PPCEXP3_S
#endif // defined(TARGET_MUSCA_A1_S)
/*ARM UART Controller PL011*/
#if defined(TARGET_MUSCA_A1_NS)
#define UART0_PL011_NS
#define UART0_PL011_DEV UART0_PL011_DEV_NS
#define uart0_tx_irq_handler UARTTX0_Handler
#define uart0_rx_irq_handler UARTRX0_Handler
#define uart0_rx_timeout_irq_handler UART0_RxTimeout_IRQHandler
#endif
#if defined(TARGET_MUSCA_A1_NS)
#define UART1_PL011_NS
#define UART1_PL011_DEV UART1_PL011_DEV_NS
#define uart1_tx_irq_handler UARTTX1_Handler
#define uart1_rx_irq_handler UARTRX1_Handler
#define uart1_rx_timeout_irq_handler UART1_RxTimeout_IRQHandler
#endif
/* CMSDK Timers */
#if defined(TARGET_MUSCA_A1_S)
#define CMSDK_TIMER0_S
#endif
#if defined(TARGET_MUSCA_A1_NS)
#define CMSDK_TIMER0_NS
#define CMSDK_TIMER0_DEV CMSDK_TIMER0_DEV_NS
#endif
#if defined(TARGET_MUSCA_A1_S)
#define CMSDK_TIMER1_S
#endif
#if defined(TARGET_MUSCA_A1_NS)
#define CMSDK_TIMER1_NS
#endif
#if defined(TARGET_MUSCA_A1_S)
/* Cadence QSPI Flash Controller */
#define QSPI_IP6514E_S
#define QSPI_IP6514E_NS
/* MT25QL Flash memory library */
#define MT25QL_S
#define MT25QL_NS
#endif // defined(TARGET_MUSCA_A1_S)
#if defined(TARGET_MUSCA_A1_NS)
/* GP Timer */
#define GP_TIMER_NS
#define GP_TIMER_DEV GP_TIMER_DEV_NS
@ -144,6 +81,5 @@
#define USEC_REPORTED_BITS (32 - USEC_REPORTED_SHIFT)
#define UART_DEFAULT_BAUD_RATE 9600U
#endif // TARGET_MUSCA_A1_NS
#endif /* __ARM_LTD_DEVICE_CFG_H__ */

View File

@ -30,7 +30,6 @@
extern "C" {
#endif
#if TARGET_MUSCA_A1_NS
struct serial_s {
struct uart_pl011_dev_t *uart_dev;
UARTName uart_index; /* UART device number */
@ -38,7 +37,6 @@ struct serial_s {
IRQn_Type rx_irq;
IRQn_Type rx_timeout_irq;
};
#endif // TARGET_MUSCA_A1_NS
#if DEVICE_FLASH
struct flash_s {

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2018-2020 Arm Limited. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
#ifndef __RTE_DEVICE_H__
#define __RTE_DEVICE_H__
// <e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
// <i> Configuration settings for Driver_ISRAM0_MPC in component ::Drivers:MPC
#define RTE_ISRAM0_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM0_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
// <i> Configuration settings for Driver_SRAM1_MPC in component ::Drivers:MPC
#define RTE_ISRAM1_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM1_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
// <i> Configuration settings for Driver_ISRAM2_MPC in component ::Drivers:MPC
#define RTE_ISRAM2_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_ISRAM2_MPC]
// <e> MPC (Memory Protection Controller) [Driver_ISRAM3_MPC]
// <i> Configuration settings for Driver_SRAM2_MPC in component ::Drivers:MPC
#define RTE_ISRAM3_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_SRAM3_MPC]
// <e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
// <i> Configuration settings for Driver_CODE_SRAM_MPC in component ::Drivers:MPC
#define RTE_CODE_SRAM_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_CODE_SRAM_MPC]
// <e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
// <i> Configuration settings for Driver_QSPI_MPC in component ::Drivers:MPC
#define RTE_QSPI_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_QSPI_MPC]
// <e> MPC (Memory Protection Controller) [Driver_EFLASH0_MPC]
// <i> Configuration settings for Driver_EFLASH0_MPC in component ::Drivers:MPC
#define RTE_EFLASH0_MPC 1
// </e> MPC (Memory Protection Controller) [Driver_EFLASH0_MPC]
// <e> MPC (Memory Protection Controller) [Driver_EFLASH1_MPC]
// <i> Configuration settings for Driver_EFLASH1_MPC in component ::Drivers:MPC
#define RTE_EFLASH1_MPC 0
// </e> MPC (Memory Protection Controller) [Driver_EFLASH1_MPC]
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
// <i> Configuration settings for Driver_USART0 in component ::Drivers:USART
#define RTE_USART0 1
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART0]
// <e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
// <i> Configuration settings for Driver_USART1 in component ::Drivers:USART
#define RTE_USART1 1
// </e> USART (Universal synchronous - asynchronous receiver transmitter) [Driver_USART1]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
// <i> Configuration settings for Driver_AHB_PPC0 in component ::Drivers:PPC
#define RTE_AHB_PPC0 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPC0]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
// <i> Configuration settings for Driver_AHB_PPCEXP0 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP0 1
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP0]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
// <i> Configuration settings for Driver_AHB_PPCEXP1 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP1 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP1]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
// <i> Configuration settings for Driver_AHB_PPCEXP2 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP2 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP2]
// <e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
// <i> Configuration settings for Driver_AHB_PPCEXP3 in component ::Drivers:PPC
#define RTE_AHB_PPCEXP3 0
// </e> PPC (Peripheral Protection Controller) [Driver_AHB_PPCEXP3]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
// <i> Configuration settings for Driver_APB_PPC0 in component ::Drivers:PPC
#define RTE_APB_PPC0 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC0]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
// <i> Configuration settings for Driver_APB_PPC1 in component ::Drivers:PPC
#define RTE_APB_PPC1 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPC1]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
// <i> Configuration settings for Driver_APB_PPCEXP0 in component ::Drivers:PPC
#define RTE_APB_PPCEXP0 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP0]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
// <i> Configuration settings for Driver_APB_PPCEXP1 in component ::Drivers:PPC
#define RTE_APB_PPCEXP1 1
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP1]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
// <i> Configuration settings for Driver_APB_PPCEXP2 in component ::Drivers:PPC
#define RTE_APB_PPCEXP2 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP2]
// <e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
// <i> Configuration settings for Driver_APB_PPCEXP3 in component ::Drivers:PPC
#define RTE_APB_PPCEXP3 0
// </e> PPC (Peripheral Protection Controller) [Driver_APB_PPCEXP3]
// <e> FLASH (Flash Memory) [Driver_FLASH0]
// <i> Configuration settings for Driver_FLASH0 in component ::Drivers:FLASH
#define RTE_FLASH0 1
// </e> FLASH (Flash Memory) [Driver_FLASH0]
#endif /* __RTE_DEVICE_H__ */

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2018-2020 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_DRIVER_CONFIG_H__
#define __CMSIS_DRIVER_CONFIG_H__
#include "device_cfg.h"
#include "platform_description.h"
#include "device_definition.h"
#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S
#define MPC_ISRAM1_DEV MPC_ISRAM1_DEV_S
#define MPC_ISRAM2_DEV MPC_ISRAM2_DEV_S
#define MPC_ISRAM3_DEV MPC_ISRAM3_DEV_S
#define MPC_CODE_SRAM_DEV MPC_CODE_SRAM_DEV_S
#define MPC_QSPI_DEV MPC_QSPI_DEV_S
#define MPC_EFLASH0_DEV MPC_EFLASH0_DEV_S
#define AHB_PPC0_DEV AHB_PPC0_DEV_S
#define AHB_PPCEXP0_DEV AHB_PPCEXP0_DEV_S
#define AHB_PPCEXP1_DEV AHB_PPCEXP1_DEV_S
#define AHB_PPCEXP2_DEV AHB_PPCEXP2_DEV_S
#define AHB_PPCEXP3_DEV AHB_PPCEXP3_DEV_S
#define APB_PPC0_DEV APB_PPC0_DEV_S
#define APB_PPC1_DEV APB_PPC1_DEV_S
#define APB_PPCEXP0_DEV APB_PPCEXP0_DEV_S
#define APB_PPCEXP1_DEV APB_PPCEXP1_DEV_S
#define APB_PPCEXP2_DEV APB_PPCEXP2_DEV_S
#define APB_PPCEXP3_DEV APB_PPCEXP3_DEV_S
#define MUSCA_B1_SCC_DEV MUSCA_B1_SCC_DEV_S
#endif /* __CMSIS_DRIVER_CONFIG_H__ */

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2013-2016 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Jan 2014
* $Revision: V2.00
*
* Project: Common Driver definitions
*/
/* History:
* Version 2.00
* Changed prefix ARM_DRV -> ARM_DRIVER
* Added General return codes definitions
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.00
* Initial release
*/
#ifndef __DRIVER_COMMON_H
#define __DRIVER_COMMON_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor))
/**
\brief Driver Version
*/
typedef struct _ARM_DRIVER_VERSION {
uint16_t api; ///< API version
uint16_t drv; ///< Driver version
} ARM_DRIVER_VERSION;
/* General return codes */
#define ARM_DRIVER_OK 0 ///< Operation succeeded
#define ARM_DRIVER_ERROR -1 ///< Unspecified error
#define ARM_DRIVER_ERROR_BUSY -2 ///< Driver is busy
#define ARM_DRIVER_ERROR_TIMEOUT -3 ///< Timeout occurred
#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported
#define ARM_DRIVER_ERROR_PARAMETER -5 ///< Parameter error
#define ARM_DRIVER_ERROR_SPECIFIC -6 ///< Start of driver specific errors
/**
\brief General power states
*/
typedef enum _ARM_POWER_STATE {
ARM_POWER_OFF, ///< Power off: no operation possible
ARM_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events
ARM_POWER_FULL ///< Power on: full operation at maximum performance
} ARM_POWER_STATE;
#endif /* __DRIVER_COMMON_H */

View File

@ -1,152 +0,0 @@
/*
* Copyright (c) 2016-2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DRIVER_MPC_H
#define __DRIVER_MPC_H
#include "Driver_Common.h"
/* API version */
#define ARM_MPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
/* Error code returned by the driver functions */
#define ARM_MPC_ERR_NOT_INIT (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< MPC not initialized */
#define ARM_MPC_ERR_NOT_IN_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Address does not belong to a range controlled by the MPC */
#define ARM_MPC_ERR_NOT_ALIGNED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Address is not aligned on the block size of this MPC */
#define ARM_MPC_ERR_INVALID_RANGE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given address range to configure is invalid
#define ARM_MPC_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< The given range cannot be accessed with the wanted security attributes */
#define ARM_MPC_ERR_UNSPECIFIED (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Unspecified error */
/* Security attribute used in various place of the API */
typedef enum _ARM_MPC_SEC_ATTR {
ARM_MPC_ATTR_SECURE, ///< Secure attribute
ARM_MPC_ATTR_NONSECURE, ///< Non-secure attribute
/* Used when getting the configuration of a memory range and some blocks are
* secure whereas some other are non secure */
ARM_MPC_ATTR_MIXED, ///< Mixed attribute
} ARM_MPC_SEC_ATTR;
/* Function documentation */
/**
\fn ARM_DRIVER_VERSION ARM_MPC_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn int32_t ARM_MPC_Initialize (void)
\brief Initialize MPC Interface.
\return Returns error code.
\fn int32_t ARM_MPC_Uninitialize (void)
\brief De-initialize MPC Interface. The controlled memory region
should not be accessed after a call to this function, as
it is allowed to configure everything to be secure (to
prevent information leak for example).
\return Returns error code.
\fn int32_t ARM_MPC_GetBlockSize (uint32_t* blk_size)
\brief Get the block size of the MPC. All regions must be aligned
on this block size (base address and limit+1 address).
\param[out] blk_size: The block size in bytes.
\return Returns error code.
\fn int32_t ARM_MPC_GetCtrlConfig (uint32_t* ctrl_val)
\brief Get some information on how the MPC IP is configured.
\param[out] ctrl_val: MPC control configuration
\return Returns error code.
\fn int32_t ARM_MPC_SetCtrlConfig (uint32_t ctrl)
\brief Set new control configuration for the MPC IP.
\param[in] ctrl: New control configuration.
\return Returns error code.
\fn int32_t ARM_MPC_ConfigRegion (uintptr_t base,
uintptr_t limit,
ARM_MPC_SEC_ATTR attr)
\brief Configure a memory region (base and limit included).
Both base and limit addresses must belong to the same
memory range, and this range must be managed by this MPC.
Also, some ranges are only allowed to be configured as
secure/non-secure, because of hardware requirements
(security aliases), and only a relevant security attribute
is therefore allowed for such ranges.
\param[in] base: Base address of the region to configure. This
bound is included in the configured region.
This must be aligned on the block size of this MPC.
\param[in] limit: Limit address of the region to configure. This
bound is included in the configured region.
Limit+1 must be aligned on the block size of this MPC.
\param[in] attr: Wanted security attribute of the region.
\return Returns error code.
\fn int32_t ARM_MPC_GetRegionConfig (uintptr_t base,
uintptr_t limit,
ARM_MPC_SEC_ATTR *attr)
\brief Gets a memory region (base and limit included).
\param[in] base: Base address of the region to poll. This
bound is included. It does not need to be aligned
in any way.
\param[in] limit: Limit address of the region to poll. This
bound is included. (limit+1) does not need to be aligned
in any way.
\param[out] attr: Security attribute of the region.
If the region has mixed secure/non-secure,
a special value is returned (\ref ARM_MPC_SEC_ATTR).
In case base and limit+1 addresses are not aligned on
the block size, the enclosing region with base and
limit+1 aligned on block size will be queried.
In case of early termination of the function (error), the
security attribute will be set to ARM_MPC_ATTR_MIXED.
\return Returns error code.
\fn int32_t ARM_MPC_EnableInterrupt (void)
\brief Enable MPC interrupt.
\return Returns error code.
\fn void ARM_MPC_DisableInterrupt (void)
\brief Disable MPC interrupt.
\fn void ARM_MPC_ClearInterrupt (void)
\brief Clear MPC interrupt.
\fn uint32_t ARM_MPC_InterruptState (void)
\brief MPC interrupt state.
\return Returns 1 if the interrupt is active, 0 otherwise.
\fn int32_t ARM_MPC_LockDown (void)
\brief Lock down the MPC configuration.
\return Returns error code.
*/
/**
* \brief Access structure of the MPC Driver.
*/
typedef struct _ARM_DRIVER_MPC {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_MPC_GetVersion : Get driver version.
int32_t (*Initialize) (void); ///< Pointer to \ref ARM_MPC_Initialize : Initialize the MPC Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_MPC_Uninitialize : De-initialize the MPC Interface.
int32_t (*GetBlockSize) (uint32_t* blk_size); ///< Pointer to \ref ARM_MPC_GetBlockSize : Get MPC block size
int32_t (*GetCtrlConfig) (uint32_t* ctrl_val); ///< Pointer to \ref ARM_MPC_GetCtrlConfig : Get the MPC control configuration flags.
int32_t (*SetCtrlConfig) (uint32_t ctrl); ///< Pointer to \ref ARM_MPC_SetCtrlConfig : Set the MPC control configuration flags.
int32_t (*ConfigRegion) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR attr); ///< Pointer to \ref ARM_MPC_ConfigRegion : Configure a region using the driver for the specific MPC.
int32_t (*GetRegionConfig) (uintptr_t base, uintptr_t limit, ARM_MPC_SEC_ATTR *attr); ///< Pointer to \ref ARM_MPC_GetRegionConfig : Get the configuration of a specific region on this MPC.
int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_MPC_EnableInterrupt : Enable MPC interrupt.
void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_MPC_DisableInterrupt : Disable MPC interrupt.
void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_MPC_ClearInterrupt : Clear MPC interrupt.
uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_MPC_InterruptState : MPC interrupt State.
int32_t (*LockDown) (void); ///< Pointer to \ref ARM_MPC_LockDown : Lock down the MPC configuration.
} const ARM_DRIVER_MPC;
#endif /* __DRIVER_MPC_H */

View File

@ -1,970 +0,0 @@
/*
* Copyright (c) 2016-2019 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Driver_PPC.h"
#include "cmsis_driver_config.h"
#include "RTE_Device.h"
/* Driver version */
#define ARM_PPC_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_PPC_API_VERSION,
ARM_PPC_DRV_VERSION
};
static ARM_DRIVER_VERSION ARM_PPC_GetVersion(void)
{
return DriverVersion;
}
#if (RTE_AHB_PPC0)
/* AHB PPC0 Driver wrapper functions */
static int32_t AHB_PPC0_Initialize(void)
{
ppc_sse200_init(&AHB_PPC0_DEV, AHB_PPC0);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPC0_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t AHB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPC0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPC0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPC0_DEV, periph);
}
static uint32_t AHB_PPC0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPC0_DEV, periph);
}
static int32_t AHB_PPC0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPC0_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPC0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPC0_DEV);
}
static void AHB_PPC0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPC0_DEV);
}
static uint32_t AHB_PPC0_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPC0_DEV);
}
/* AHB PPC0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPC0;
ARM_DRIVER_PPC Driver_AHB_PPC0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPC0_Initialize,
.Uninitialize = AHB_PPC0_Uninitialize,
.ConfigPeriph = AHB_PPC0_ConfigPeriph,
.IsPeriphSecure = AHB_PPC0_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPC0_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPC0_EnableInterrupt,
.DisableInterrupt = AHB_PPC0_DisableInterrupt,
.ClearInterrupt = AHB_PPC0_ClearInterrupt,
.InterruptState = AHB_PPC0_InterruptState
};
#endif /* RTE_AHB_PPC0 */
#if (RTE_AHB_PPCEXP0)
/* AHB PPCEXP0 Driver wrapper functions */
static int32_t AHB_PPCEXP0_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP0_DEV, AHB_PPC_EXP0);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP0_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP0_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP0_DEV, periph);
}
static uint32_t AHB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP0_DEV, periph);
}
static int32_t AHB_PPCEXP0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP0_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP0_DEV);
}
static void AHB_PPCEXP0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP0_DEV);
}
static uint32_t AHB_PPCEXP0_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP0_DEV);
}
/* AHB PPCEXP0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0;
ARM_DRIVER_PPC Driver_AHB_PPCEXP0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP0_Initialize,
.Uninitialize = AHB_PPCEXP0_Uninitialize,
.ConfigPeriph = AHB_PPCEXP0_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP0_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP0_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP0_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP0_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP0_ClearInterrupt,
.InterruptState = AHB_PPCEXP0_InterruptState
};
#endif /* RTE_AHB_PPCEXP0 */
#if (RTE_AHB_PPCEXP1)
/* AHB PPCEXP1 Driver wrapper functions */
static int32_t AHB_PPCEXP1_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP1_DEV, AHB_PPC_EXP1);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP1_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP1_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP1_DEV, periph);
}
static uint32_t AHB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP1_DEV, periph);
}
static int32_t AHB_PPCEXP1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP1_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP1_DEV);
}
static void AHB_PPCEXP1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP1_DEV);
}
static uint32_t AHB_PPCEXP1_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP1_DEV);
}
/* AHB PPCEXP1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP1;
ARM_DRIVER_PPC Driver_AHB_PPCEXP1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP1_Initialize,
.Uninitialize = AHB_PPCEXP1_Uninitialize,
.ConfigPeriph = AHB_PPCEXP1_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP1_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP1_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP1_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP1_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP1_ClearInterrupt,
.InterruptState = AHB_PPCEXP1_InterruptState
};
#endif /* RTE_AHB_PPCEXP1 */
#if (RTE_AHB_PPCEXP2)
/* AHB PPCEXP2 Driver wrapper functions */
static int32_t AHB_PPCEXP2_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP2_DEV, AHB_PPC_EXP2);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP2_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP2_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP2_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP2_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP2_DEV, periph);
}
static uint32_t AHB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP2_DEV, periph);
}
static int32_t AHB_PPCEXP2_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP2_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP2_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP2_DEV);
}
static void AHB_PPCEXP2_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP2_DEV);
}
static uint32_t AHB_PPCEXP2_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP2_DEV);
}
/* AHB PPCEXP2 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP2;
ARM_DRIVER_PPC Driver_AHB_PPCEXP2 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP2_Initialize,
.Uninitialize = AHB_PPCEXP2_Uninitialize,
.ConfigPeriph = AHB_PPCEXP2_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP2_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP2_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP2_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP2_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP2_ClearInterrupt,
.InterruptState = AHB_PPCEXP2_InterruptState
};
#endif /* RTE_AHB_PPCEXP2 */
#if (RTE_AHB_PPCEXP3)
/* AHB PPCEXP3 Driver wrapper functions */
static int32_t AHB_PPCEXP3_Initialize(void)
{
ppc_sse200_init(&AHB_PPCEXP3_DEV, AHB_PPC_EXP3);
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP3_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t AHB_PPCEXP3_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&AHB_PPCEXP3_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t AHB_PPCEXP3_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&AHB_PPCEXP3_DEV, periph);
}
static uint32_t AHB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&AHB_PPCEXP3_DEV, periph);
}
static int32_t AHB_PPCEXP3_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&AHB_PPCEXP3_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void AHB_PPCEXP3_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&AHB_PPCEXP3_DEV);
}
static void AHB_PPCEXP3_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&AHB_PPCEXP3_DEV);
}
static uint32_t AHB_PPCEXP3_InterruptState(void)
{
return ppc_sse200_irq_state(&AHB_PPCEXP3_DEV);
}
/* AHB PPCEXP3 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP3;
ARM_DRIVER_PPC Driver_AHB_PPCEXP3 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = AHB_PPCEXP3_Initialize,
.Uninitialize = AHB_PPCEXP3_Uninitialize,
.ConfigPeriph = AHB_PPCEXP3_ConfigPeriph,
.IsPeriphSecure = AHB_PPCEXP3_IsPeriphSecure,
.IsPeriphPrivOnly = AHB_PPCEXP3_IsPeriphPrivOnly,
.EnableInterrupt = AHB_PPCEXP3_EnableInterrupt,
.DisableInterrupt = AHB_PPCEXP3_DisableInterrupt,
.ClearInterrupt = AHB_PPCEXP3_ClearInterrupt,
.InterruptState = AHB_PPCEXP3_InterruptState
};
#endif /* RTE_AHB_PPCEXP3 */
#if (RTE_APB_PPC0)
/* APB PPC0 Driver wrapper functions */
static int32_t APB_PPC0_Initialize(void)
{
ppc_sse200_init(&APB_PPC0_DEV, APB_PPC0);
return ARM_DRIVER_OK;
}
static int32_t APB_PPC0_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t APB_PPC0_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPC0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPC0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPC0_DEV, periph);
}
static uint32_t APB_PPC0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPC0_DEV, periph);
}
static int32_t APB_PPC0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPC0_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPC0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPC0_DEV);
}
static void APB_PPC0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPC0_DEV);
}
static uint32_t APB_PPC0_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPC0_DEV);
}
/* APB PPC0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPC0;
ARM_DRIVER_PPC Driver_APB_PPC0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPC0_Initialize,
.Uninitialize = APB_PPC0_Uninitialize,
.ConfigPeriph = APB_PPC0_ConfigPeriph,
.IsPeriphSecure = APB_PPC0_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPC0_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPC0_EnableInterrupt,
.DisableInterrupt = APB_PPC0_DisableInterrupt,
.ClearInterrupt = APB_PPC0_ClearInterrupt,
.InterruptState = APB_PPC0_InterruptState
};
#endif /* RTE_APB_PPC0 */
#if (RTE_APB_PPC1)
/* APB PPC1 Driver wrapper functions */
static int32_t APB_PPC1_Initialize(void)
{
ppc_sse200_init(&APB_PPC1_DEV, APB_PPC1);
return ARM_DRIVER_OK;
}
static int32_t APB_PPC1_Uninitialize(void)
{
/* Nothing to be done*/
return ARM_DRIVER_OK;
}
static int32_t APB_PPC1_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPC1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPC1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPC1_DEV, periph);
}
static uint32_t APB_PPC1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPC1_DEV, periph);
}
static int32_t APB_PPC1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPC1_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPC1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPC1_DEV);
}
static void APB_PPC1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPC1_DEV);
}
static uint32_t APB_PPC1_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPC1_DEV);
}
/* APB PPC1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPC1;
ARM_DRIVER_PPC Driver_APB_PPC1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPC1_Initialize,
.Uninitialize = APB_PPC1_Uninitialize,
.ConfigPeriph = APB_PPC1_ConfigPeriph,
.IsPeriphSecure = APB_PPC1_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPC1_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPC1_EnableInterrupt,
.DisableInterrupt = APB_PPC1_DisableInterrupt,
.ClearInterrupt = APB_PPC1_ClearInterrupt,
.InterruptState = APB_PPC1_InterruptState
};
#endif /* RTE_APB_PPC1 */
#if (RTE_APB_PPCEXP0)
/* APB PPCEXP0 Driver wrapper functions */
static int32_t APB_PPCEXP0_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP0_DEV, APB_PPC_EXP0);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP0_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP0_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP0_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP0_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP0_DEV, periph);
}
static uint32_t APB_PPCEXP0_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP0_DEV, periph);
}
static int32_t APB_PPCEXP0_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP0_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP0_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP0_DEV);
}
static void APB_PPCEXP0_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP0_DEV);
}
static uint32_t APB_PPCEXP0_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP0_DEV);
}
/* APB PPCEXP0 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP0;
ARM_DRIVER_PPC Driver_APB_PPCEXP0 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP0_Initialize,
.Uninitialize = APB_PPCEXP0_Uninitialize,
.ConfigPeriph = APB_PPCEXP0_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP0_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP0_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP0_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP0_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP0_ClearInterrupt,
.InterruptState = APB_PPCEXP0_InterruptState
};
#endif /* RTE_APB_PPCEXP0 */
#if (RTE_APB_PPCEXP1)
/* APB PPCEXP1 Driver wrapper functions */
static int32_t APB_PPCEXP1_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP1_DEV, APB_PPC_EXP1);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP1_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP1_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP1_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP1_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP1_DEV, periph);
}
static uint32_t APB_PPCEXP1_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP1_DEV, periph);
}
static int32_t APB_PPCEXP1_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP1_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP1_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP1_DEV);
}
static void APB_PPCEXP1_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP1_DEV);
}
static uint32_t APB_PPCEXP1_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP1_DEV);
}
/* APB PPCEXP1 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP1;
ARM_DRIVER_PPC Driver_APB_PPCEXP1 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP1_Initialize,
.Uninitialize = APB_PPCEXP1_Uninitialize,
.ConfigPeriph = APB_PPCEXP1_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP1_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP1_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP1_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP1_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP1_ClearInterrupt,
.InterruptState = APB_PPCEXP1_InterruptState
};
#endif /* RTE_APB_PPCEXP1 */
#if (RTE_APB_PPCEXP2)
/* APB PPCEXP2 Driver wrapper functions */
static int32_t APB_PPCEXP2_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP2_DEV, APB_PPC_EXP2);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP2_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP2_ConfigPeriph(uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP2_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP2_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP2_DEV, periph);
}
static uint32_t APB_PPCEXP2_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP2_DEV, periph);
}
static int32_t APB_PPCEXP2_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP2_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP2_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP2_DEV);
}
static void APB_PPCEXP2_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP2_DEV);
}
static uint32_t APB_PPCEXP2_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP2_DEV);
}
/* APB PPCEXP2 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP2;
ARM_DRIVER_PPC Driver_APB_PPCEXP2 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP2_Initialize,
.Uninitialize = APB_PPCEXP2_Uninitialize,
.ConfigPeriph = APB_PPCEXP2_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP2_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP2_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP2_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP2_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP2_ClearInterrupt,
.InterruptState = APB_PPCEXP2_InterruptState
};
#endif /* RTE_APB_PPCEXP2 */
#if (RTE_APB_PPCEXP3)
/* APB PPCEXP3 Driver wrapper functions */
static int32_t APB_PPCEXP3_Initialize(void)
{
ppc_sse200_init(&APB_PPCEXP3_DEV, APB_PPC_EXP3);
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP3_Uninitialize(void)
{
/* Nothing to be done */
return ARM_DRIVER_OK;
}
static int32_t APB_PPCEXP3_ConfigPeriph(uint8_t periph, ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_config_peripheral(&APB_PPCEXP3_DEV, periph,
(enum ppc_sse200_sec_attr_t)sec_attr,
(enum ppc_sse200_priv_attr_t)priv_attr);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static uint32_t APB_PPCEXP3_IsPeriphSecure(uint8_t periph)
{
return ppc_sse200_is_periph_secure(&APB_PPCEXP3_DEV, periph);
}
static uint32_t APB_PPCEXP3_IsPeriphPrivOnly(uint8_t periph)
{
return ppc_sse200_is_periph_priv_only(&APB_PPCEXP3_DEV, periph);
}
static int32_t APB_PPCEXP3_EnableInterrupt(void)
{
enum ppc_sse200_error_t ret;
ret = ppc_sse200_irq_enable(&APB_PPCEXP3_DEV);
if (ret != PPC_SSE200_ERR_NONE) {
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
static void APB_PPCEXP3_DisableInterrupt(void)
{
ppc_sse200_irq_disable(&APB_PPCEXP3_DEV);
}
static void APB_PPCEXP3_ClearInterrupt(void)
{
ppc_sse200_clear_irq(&APB_PPCEXP3_DEV);
}
static uint32_t APB_PPCEXP3_InterruptState(void)
{
return ppc_sse200_irq_state(&APB_PPCEXP3_DEV);
}
/* APB PPCEXP3 Driver CMSIS access structure */
extern ARM_DRIVER_PPC Driver_APB_PPCEXP3;
ARM_DRIVER_PPC Driver_APB_PPCEXP3 = {
.GetVersion = ARM_PPC_GetVersion,
.Initialize = APB_PPCEXP3_Initialize,
.Uninitialize = APB_PPCEXP3_Uninitialize,
.ConfigPeriph = APB_PPCEXP3_ConfigPeriph,
.IsPeriphSecure = APB_PPCEXP3_IsPeriphSecure,
.IsPeriphPrivOnly = APB_PPCEXP3_IsPeriphPrivOnly,
.EnableInterrupt = APB_PPCEXP3_EnableInterrupt,
.DisableInterrupt = APB_PPCEXP3_DisableInterrupt,
.ClearInterrupt = APB_PPCEXP3_ClearInterrupt,
.InterruptState = APB_PPCEXP3_InterruptState
};
#endif /* RTE_APB_PPCEXP3 */

View File

@ -1,115 +0,0 @@
/*
* Copyright (c) 2016-2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CMSIS_PPC_DRV_H__
#define __CMSIS_PPC_DRV_H__
#include "Driver_Common.h"
/* API version */
#define ARM_PPC_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0)
/* Security attribute used to configure the peripheral */
typedef enum _ARM_PPC_SecAttr {
ARM_PPC_SECURE_ONLY, ///< Secure access
ARM_PPC_NONSECURE_ONLY, ///< Non-secure access
} ARM_PPC_SecAttr;
/* Privilege attribute used to configure the peripheral */
typedef enum _ARM_PPC_PrivAttr {
ARM_PPC_PRIV_AND_NONPRIV, ///< Privilege and non-privilege access
ARM_PPC_PRIV_ONLY, ///< Privilege only access
} ARM_PPC_PrivAttr;
/* Function documentation */
/**
\fn ARM_DRIVER_VERSION ARM_PPC_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn int32_t ARM_PPC_Initialize (void)
\brief Initialize PPC Interface.
\return Returns ARM error code.
\fn int32_t ARM_PPC_Uninitialize (void)
\brief De-initialize MPC Interface.
\return Returns ARM error code.
\fn int32_t ARM_PPC_ConfigPeriph (uint8_t periph,
ARM_PPC_SecAttr sec_attr,
ARM_PPC_PrivAttr priv_attr)
\brief Configures a peripheral controlled by the given PPC.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
\param[in] sec_attr: Secure attribute value.
\param[in] priv_attr: Privilege attrivute value.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns ARM error code.
\fn int32_t ARM_PPC_IsPeriphSecure (uint8_t periph)
\brief Check if the peripheral is configured to be secure.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns 1 if the peripheral is configured as secure,
0 for non-secure.
\fn uint32_t ARM_PPC_IsPeriphPrivOnly (uint8_t periph)
\brief Check if the peripheral is configured to be privilege only.
\param[in] periph: Peripheral position in SPCTRL and NSPCTRL registers.
Secure Privilege Control Block ( SPCTRL )
Non-Secure Privilege Control Block ( NSPCTRL )
\return Returns 1 if the peripheral is configured as privilege access
only, 0 for privilege and unprivilege access mode.
\fn int32_t ARM_PPC_EnableInterrupt (void)
\brief Enable PPC interrupt.
\return Returns ARM error code.
\fn void ARM_PPC_DisableInterrupt (void)
\brief Disable PPC interrupt.
\fn void ARM_PPC_ClearInterrupt (void)
\brief Clear PPC interrupt.
\fn int32_t ARM_PPC_InterruptState (void)
\brief PPC interrupt state.
\return Returns 1 if the interrupt is active, 0 otherwise.
*/
/**
* \brief Access structure of the MPC Driver.
*/
typedef struct _ARM_DRIVER_PPC {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_PPC_GetVersion : Get driver version.
int32_t (*Initialize) (void); ///< Pointer to \ref ARM_PPC_Initialize : Initialize the PPC Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_PPC_Uninitialize : De-initialize the PPC Interface.
int32_t (*ConfigPeriph) (uint8_t periph, ARM_PPC_SecAttr sec_attr, ARM_PPC_PrivAttr priv_attr); ///< Pointer to \ref ARM_PPC_ConfigPeriph : Configure a peripheral controlled by the PPC.
uint32_t (*IsPeriphSecure) (uint8_t periph); ///< Pointer to \ref IsPeriphSecure : Check if the peripheral is configured to be secure.
uint32_t (*IsPeriphPrivOnly) (uint8_t periph); ///< Pointer to \ref IsPeriphPrivOnly : Check if the peripheral is configured to be privilege only.
int32_t (*EnableInterrupt) (void); ///< Pointer to \ref ARM_PPC_EnableInterrupt : Enable PPC interrupt.
void (*DisableInterrupt) (void); ///< Pointer to \ref ARM_PPC_DisableInterrupt : Disable PPC interrupt.
void (*ClearInterrupt) (void); ///< Pointer to \ref ARM_PPC_ClearInterrupt : Clear PPC interrupt.
uint32_t (*InterruptState) (void); ///< Pointer to \ref ARM_PPC_InterruptState : PPC interrupt State.
} const ARM_DRIVER_PPC;
#endif /* __CMSIS_PPC_DRV_H__ */

View File

@ -1,901 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
/* Use memcpy function */
#include <string.h>
#include "mt25ql_flash_lib.h"
#include "qspi_ip6514e_drv.h"
/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
/** Getter bit manipulation macro */
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
#define BITS_PER_WORD 32U
#define BYTES_PER_WORD 4U
#define ARG_NOT_USED 0
#define ARG_PTR_NOT_USED NULL
/** MT25QL used command */
#define WRITE_ENABLE_CMD 0x06U
#define READ_ENHANCED_VOLATILE_CFG_REG_CMD 0x65U
#define WRITE_ENHANCED_VOLATILE_CFG_REG_CMD 0x61U
#define READ_VOLATILE_CFG_REG_CMD 0x85U
#define WRITE_VOLATILE_CFG_REG_CMD 0x81U
#define READ_FLAG_STATUS_REG_CMD 0x70U
#define SUBSECTOR_ERASE_32KB_CMD 0x52U
#define SUBSECTOR_ERASE_4KB_CMD 0x20U
#define SECTOR_ERASE_CMD 0xD8U
#define BULK_ERASE_CMD 0xC7U
/*
* The baud rate divisor in \ref mt25ql_dev_t needs to be configured adequately
* to handle those commands.
*/
#define QUAD_OUTPUT_FAST_READ_CMD 0x6BU
#define FAST_READ_CMD 0x0BU
#define READ_CMD 0x03U
#define QUAD_INPUT_FAST_PROGRAM_CMD 0x32U
#define PAGE_PROGRAM_CMD 0x02U
/** MT25QL Enhanced Volatile Configuration Register access */
#define ENHANCED_VOLATILE_CFG_REG_LEN 1U
#define ENHANCED_VOLATILE_CFG_REG_QSPI_POS 7U
#define ENHANCED_VOLATILE_CFG_REG_DSPI_POS 6U
/** MT25QL Volatile Configuration Register access */
#define VOLATILE_CFG_REG_LEN 1U
#define VOLATILE_CFG_REG_DUMMY_CYCLES_POS 4U
#define VOLATILE_CFG_REG_DUMMY_CYCLES_BITS 4U
/** MT25QL Flag Status Register access */
#define FLAG_STATUS_REG_LEN 1U
#define FLAG_STATUS_REG_READY_POS 7U
/*
* 10 is the minimal number of dummy clock cycles needed to reach the maximal
* frequency of the Quad Output Fast Read Command.
*/
#define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES 10U
#define FAST_READ_DUMMY_CYCLES 8U
#define RESET_STATE_DUMMY_CYCLES 8U
#define DEFAULT_READ_DUMMY_CYCLES 0U
#define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES 0U
#define PAGE_PROGRAM_DUMMY_CYCLES 0U
/* Only up to 8 bytes can be read or written using the Flash commands. */
#define CMD_DATA_MAX_SIZE 8U
/**
* \brief Change specific bits in a 32 bits word.
*
* \param[in,out] word Pointer of the word to change
* \param[in] bits bits_length bits to put at bits_pos in the word
* pointed
* \param[in] bits_length Number of bits to change
* \param[in] bits_pos Position of the bits to change
*
* \note This function will do nothing if the parameters given are incorrect:
* * word is NULL
* * bits_length + bits_pos > 32
* * bits_length is 0
*/
static void change_bits_in_word(volatile uint32_t *word,
uint32_t bits,
uint32_t bits_length,
uint32_t bits_pos)
{
uint32_t mask;
if ((word == NULL) ||
((bits_length + bits_pos) > BITS_PER_WORD) ||
(bits_length == 0U)) {
/* Silently fail */
return;
}
/* Change all the bits */
if (bits_length == BITS_PER_WORD) {
*word = bits;
return;
}
mask = ((1U << bits_length) - 1);
/*
* We change the bits in three steps:
* - clear bits_length bits with zeroes at bits_pos in the word
* - mask bits in case it contains more than bits_length bits
* - set the new bits in the cleared word
* Because the data pointed by word is only read once, the data will still
* be coherent after an interruption that changes it.
*/
*word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
}
/**
* \brief Send the Write Enable command, needed before any write.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*/
static void send_write_enable(struct mt25ql_dev_t* dev)
{
qspi_ip6514e_send_simple_cmd(dev->controller, WRITE_ENABLE_CMD);
}
/**
* \brief Set SPI mode on the flash device and on the controller.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] spi_mode SPI mode to be set on flash device and controller
* \ref qspi_ip6514e_spi_mode_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev,
enum qspi_ip6514e_spi_mode_t spi_mode)
{
uint8_t enhanced_volatile_cfg_reg = 0;
enum qspi_ip6514e_error_t controller_error;
/* Read the Enhanced Volatile Configuration Register, modify it according
* to the requested SPI mode then write back the modified value to the
* register. This will activate the SPI mode on the flash side.
*/
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
READ_ENHANCED_VOLATILE_CFG_REG_CMD,
&enhanced_volatile_cfg_reg,
ENHANCED_VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed for
this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
switch(spi_mode) {
case QSPI_IP6514E_SPI_MODE:
/* Disable the Dual- and Quad-SPI modes.
* Clearing the bit enables the mode, setting it disables it.
*/
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
case QSPI_IP6514E_DSPI_MODE:
/* Disable the Quad-SPI mode and activate DSPI mode.
* Clearing the bit enables the mode, setting it disables it.
*/
CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
case QSPI_IP6514E_QSPI_MODE:
/* Disable the Dual-SPI mode and activate QSPI mode.
* Clearing the bit enables the mode, setting it disables it.
*/
SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
WRITE_ENHANCED_VOLATILE_CFG_REG_CMD,
&enhanced_volatile_cfg_reg,
ENHANCED_VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed for
this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Activate the requested SPI mode on the controller side as well. */
controller_error = qspi_ip6514e_set_spi_mode(dev->controller,
spi_mode,
spi_mode,
spi_mode);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
/**
* \brief Change the number of dummy clock cycles subsequent to all FAST READ
* commands.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] dummy_cycles Dummy clock cycles to set
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t change_dummy_cycles(struct mt25ql_dev_t* dev,
uint32_t dummy_cycles)
{
uint32_t volatile_cfg_reg = 0;
enum qspi_ip6514e_error_t controller_error;
/*
* Changes the number of dummy cycles in the Volatile Configuration
* Register.
*/
controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
READ_VOLATILE_CFG_REG_CMD,
&volatile_cfg_reg,
VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed
for this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
change_bits_in_word(&volatile_cfg_reg,
dummy_cycles,
VOLATILE_CFG_REG_DUMMY_CYCLES_BITS,
VOLATILE_CFG_REG_DUMMY_CYCLES_POS);
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
WRITE_VOLATILE_CFG_REG_CMD,
&volatile_cfg_reg,
VOLATILE_CFG_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles needed
for this command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
/**
* \brief Wait until the current program/erase is finished.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*/
static enum mt25ql_error_t wait_program_or_erase_complete(
struct mt25ql_dev_t* dev)
{
enum qspi_ip6514e_error_t controller_error;
uint8_t flag_status_reg = 0;
/* Wait until the ready bit of the Flag Status Register is set */
while (!GET_BIT(flag_status_reg, FLAG_STATUS_REG_READY_POS)) {
controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
READ_FLAG_STATUS_REG_CMD,
&flag_status_reg,
FLAG_STATUS_REG_LEN,
ARG_NOT_USED,
ARG_NOT_USED,
0); /* No dummy cycles
needed for this
command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
return MT25QL_ERR_NONE;
}
/**
* \brief Execute a program command that crosses the page size boundary.
*
* \param[in] dev Pointer to MT25QL device structure
* \ref mt25ql_dev_t
* \param[in] opcode Opcode for the command.
* \param[in] write_data Pointer to a memory zone where the write_len
* number of bytes are located to write for this
* command.
* \param[in] write_len Number of bytes to write for the command.
* Between 1 and 8 bytes (both included) can be
* written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will execute two commands: one to program the bytes up to
* the page boundary and another one to program the rest. It will wait
* that bytes are programmed from first command before triggering the
* second one.
* \note This function does not send a write enable command before the first
* command and does not check that bytes were programmed after the second
* command.
*/
static enum mt25ql_error_t send_boundary_cross_write_cmd(
struct mt25ql_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
/*
* Remaining bytes between the current address and the end of the current
* page.
*/
uint32_t page_remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
/* First write up to the end of the current page. */
controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
write_data, page_remainder,
addr, addr_bytes_number,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
write_data = (void *)((uint32_t)write_data + page_remainder);
addr += page_remainder;
/* Wait for the page to be written before sending new commands. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Then write the remaining data of the write_len bytes. */
send_write_enable(dev);
controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
write_data,
write_len - page_remainder,
addr, addr_bytes_number,
dummy_cycles);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
enum mt25ql_functional_state_t f_state)
{
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
switch(f_state) {
case MT25QL_FUNC_STATE_DEFAULT:
dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
dev->config_state.opcode_read = READ_CMD;
dev->config_state.dummy_cycles_read = DEFAULT_READ_DUMMY_CYCLES;
dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_FAST:
dev->config_state.spi_mode = QSPI_IP6514E_SPI_MODE;
dev->config_state.opcode_read = FAST_READ_CMD;
dev->config_state.dummy_cycles_read = FAST_READ_DUMMY_CYCLES;
dev->config_state.opcode_write = PAGE_PROGRAM_CMD;
dev->config_state.dummy_cycles_write = PAGE_PROGRAM_DUMMY_CYCLES;
break;
case MT25QL_FUNC_STATE_QUAD_FAST:
dev->config_state.spi_mode = QSPI_IP6514E_QSPI_MODE;
dev->config_state.opcode_read = QUAD_OUTPUT_FAST_READ_CMD;
dev->config_state.dummy_cycles_read =
QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
dev->config_state.opcode_write = QUAD_INPUT_FAST_PROGRAM_CMD;
dev->config_state.dummy_cycles_write =
QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
dev->config_state.func_state = f_state;
/* This function will first set the Flash memory SPI mode and then set
* the controller's SPI mode. It will fail if the two sides do not have
* the same mode when this function is called.
*/
library_error = set_spi_mode(dev, dev->config_state.spi_mode);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Set the number of dummy cycles for read commands. */
library_error = change_dummy_cycles(
dev, dev->config_state.dummy_cycles_read);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* The rest of the configuration needs the controller to be disabled */
while(!qspi_ip6514e_is_idle(dev->controller));
qspi_ip6514e_disable(dev->controller);
/* Set the baud rate divisor as configured in the device structure. */
controller_error = qspi_ip6514e_set_baud_rate_div(dev->controller,
dev->baud_rate_div);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set opcode and dummy cycles needed for read commands. */
controller_error = qspi_ip6514e_cfg_reads(
dev->controller, dev->config_state.opcode_read,
dev->config_state.dummy_cycles_read);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set opcode and dummy cycles needed for write commands. */
controller_error = qspi_ip6514e_cfg_writes(
dev->controller, dev->config_state.opcode_write,
dev->config_state.dummy_cycles_write);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Set Flash memory constants: bytes per page and address bytes. */
controller_error = qspi_ip6514e_cfg_page_size(dev->controller,
FLASH_PAGE_SIZE);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
controller_error = qspi_ip6514e_cfg_addr_bytes(dev->controller,
ADDR_BYTES);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
qspi_ip6514e_enable(dev->controller);
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_restore_reset_state(struct mt25ql_dev_t* dev)
{
enum mt25ql_error_t library_error;
/*
* This function will first change the Flash memory mode to single SPI and
* then change the controller to single SPI. It will fail if the two sides
* do not have the same mode when this function is called.
*/
library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* Set the default number of dummy cycles for direct read commands. */
library_error = change_dummy_cycles(dev, RESET_STATE_DUMMY_CYCLES);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
/* The rest of the configuration needs the controller to be disabled */
while(!qspi_ip6514e_is_idle(dev->controller));
qspi_ip6514e_disable(dev->controller);
/* Restore the default value of the QSPI controller registers. */
qspi_ip6514e_reset_regs(dev->controller);
qspi_ip6514e_enable(dev->controller);
dev->config_state = (struct mt25ql_config_state_t){ 0 };
dev->config_state.func_state = MT25QL_FUNC_STATE_NOT_INITED;
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len)
{
/*
* The direct access window size is the size of the memory that can be
* accessed with a direct access.
*/
uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
/*
* The window number is the number of times it will be needed to remap the
* address with the remap register. We move this Direct Access window first
* window_number times starting at the beginning address to read full
* windows of direct_access_window_size bytes. Then we read the remainder
* bytes.
*/
uint32_t window_number = len / direct_access_window_size;
if (data == NULL || len == 0) {
return MT25QL_ERR_WRONG_ARGUMENT;
}
if ((addr + len) >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
/*
* There is no limitation reading through a Flash page boundary hence we
* do not add the same logic here than in the write function.
*/
/* Transfer the bytes for the window_number windows first. */
for (uint32_t window = 0; window < window_number; window++) {
qspi_ip6514e_remap_addr(dev->controller, addr);
/*
* The AHB address to access the Flash memory does not change but it
* will be translated differently thanks to the remap function.
*/
memcpy(data,
(void *)dev->direct_access_start_addr,
direct_access_window_size);
len -= direct_access_window_size;
data = (void *)((uint32_t)data + direct_access_window_size);
addr += direct_access_window_size;
}
if (len) {
/* Transfer the reminder bytes */
qspi_ip6514e_remap_addr(dev->controller, addr);
memcpy(data, (void *)dev->direct_access_start_addr, len);
}
/* Disable remapping for direct accesses outside of this function. */
qspi_ip6514e_disable_remap(dev->controller);
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len)
{
enum mt25ql_error_t library_error;
/*
* The direct access window size is the size of the memory that can be
* accessed with a direct access.
*/
uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
uint32_t window_number;
/* Offset between address and the previous 32 bits aligned word */
uint32_t word_offset;
if (data == NULL || len == 0) {
return MT25QL_ERR_WRONG_ARGUMENT;
}
if ((addr + len) >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
/*
* If the remapping address is not aligned on a 32 bits boundary, a direct
* access of one word could cross a Flash page boundary. If that happens,
* the bytes of that word that are over the page boundary will instead be
* written at the beginning of the same page.
* To counter this problem, we align the remapping address and add the word
* offset to the address of the direct access for the first window only.
*/
word_offset = addr % BYTES_PER_WORD;
/* Make address aligned on a 32 bits alignment. */
addr -= word_offset;
/*
* Only direct_access_window_size address locations are available by direct
* access. We calculate the number of windows that we will need to transfer
* len bytes. We have to add in the window the offset that we add in the
* beginning.
*/
window_number = (len + word_offset) / direct_access_window_size;
/*
* This function assumes that the flash has already been erased.
* Transfer the bytes for the window_number windows first.
*/
for (uint32_t window = 0; window < window_number; window++) {
/* The controller needs to be disabled while remapping is done. */
qspi_ip6514e_remap_addr(dev->controller, addr);
/*
* The AHB address to access the Flash memory does not change but it
* will be translated differently thanks to the remap function.
*/
memcpy((void *)(dev->direct_access_start_addr + word_offset),
data,
direct_access_window_size - word_offset);
len -= (direct_access_window_size - word_offset);
data = (void *)((uint32_t)data +
(direct_access_window_size - word_offset));
addr += direct_access_window_size;
/*
* The address is now aligned, there is no need to add an offset for the
* remaining windows.
*/
word_offset = 0;
/*
* Wait until the last program operation is complete before changing
* the remap address.
*/
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
if (len) {
/* Transfer the reminder bytes */
qspi_ip6514e_remap_addr(dev->controller, addr);
memcpy((void *)(dev->direct_access_start_addr + word_offset),
data,
len);
/* Wait until the last program operation is complete */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
/*
* Disable the default remap address for direct accesses outside of this
* function.
*/
qspi_ip6514e_disable_remap(dev->controller);
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len)
{
/* With one single command only 8 bytes can be read. */
uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
enum qspi_ip6514e_error_t controller_error;
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
return MT25QL_ERR_NOT_INITED;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
dev->config_state.opcode_read,
data, CMD_DATA_MAX_SIZE, addr,
ADDR_BYTES,
dev->config_state.dummy_cycles_read);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
addr += CMD_DATA_MAX_SIZE;
len -= CMD_DATA_MAX_SIZE;
}
if (len) {
/* Read the remainder. */
controller_error = qspi_ip6514e_send_read_cmd(
dev->controller,
dev->config_state.opcode_read,
data, len, addr, ADDR_BYTES,
dev->config_state.dummy_cycles_read);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len)
{
/* With one single command only 8 bytes can be written. */
uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
return MT25QL_ERR_NOT_INITED;
}
for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
send_write_enable(dev);
/*
* Check if this command is not writing over a page boundary: first and
* last bytes are in the same page.
*/
if ((addr / FLASH_PAGE_SIZE) !=
((addr + CMD_DATA_MAX_SIZE - 1) / FLASH_PAGE_SIZE)) {
/* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
library_error = send_boundary_cross_write_cmd(
dev, dev->config_state.opcode_write,
data, CMD_DATA_MAX_SIZE, addr,
ADDR_BYTES,
dev->config_state.dummy_cycles_write);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
} else {
/* Normal case: not crossing the boundary. */
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
dev->config_state.opcode_write,
data, CMD_DATA_MAX_SIZE, addr,
ADDR_BYTES,
dev->config_state.dummy_cycles_write);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
/* Wait until the write operation is complete. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
addr += CMD_DATA_MAX_SIZE;
len -= CMD_DATA_MAX_SIZE;
}
if (len) {
/* Write the remainder. */
send_write_enable(dev);
/*
* Check if this command is not writing over a page boundary: first and
* last bytes are in the same page.
*/
if ((addr / FLASH_PAGE_SIZE) != ((addr + len - 1) / FLASH_PAGE_SIZE)) {
/* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
library_error = send_boundary_cross_write_cmd(
dev, dev->config_state.opcode_write,
data, len, addr, ADDR_BYTES,
dev->config_state.dummy_cycles_write);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
} else {
/* Normal case: not crossing the boundary. */
controller_error = qspi_ip6514e_send_write_cmd(
dev->controller,
dev->config_state.opcode_write,
data, len, addr, ADDR_BYTES,
dev->config_state.dummy_cycles_write);
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
}
/* Wait until the write operation is complete. */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return library_error;
}
}
return MT25QL_ERR_NONE;
}
enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
uint32_t addr,
enum mt25ql_erase_t erase_type)
{
enum qspi_ip6514e_error_t controller_error;
enum mt25ql_error_t library_error;
uint8_t erase_cmd;
uint32_t addr_bytes;
if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
return MT25QL_ERR_NOT_INITED;
}
send_write_enable(dev);
switch (erase_type) {
case MT25QL_ERASE_ALL_FLASH:
if (addr != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
erase_cmd = BULK_ERASE_CMD;
addr_bytes = ARG_NOT_USED;
break;
case MT25QL_ERASE_SECTOR_64K:
erase_cmd = SECTOR_ERASE_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SECTOR_64KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
case MT25QL_ERASE_SUBSECTOR_32K:
erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SUBSECTOR_32KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
case MT25QL_ERASE_SUBSECTOR_4K:
erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
addr_bytes = ADDR_BYTES;
if ((addr % SUBSECTOR_4KB) != 0) {
return MT25QL_ERR_ADDR_NOT_ALIGNED;
}
break;
default:
return MT25QL_ERR_WRONG_ARGUMENT;
}
if (addr >= dev->size) {
return MT25QL_ERR_ADDR_TOO_BIG;
}
controller_error = qspi_ip6514e_send_cmd(dev->controller,
erase_cmd,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
addr,
addr_bytes,
0); /* No dummy cycles needed for
any erase command. */
if (controller_error != QSPI_IP6514E_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
/* Wait until the erase operation is complete */
library_error = wait_program_or_erase_complete(dev);
if (library_error != MT25QL_ERR_NONE) {
return (enum mt25ql_error_t)controller_error;
}
return MT25QL_ERR_NONE;
}

View File

@ -1,271 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This library provides functions to control the MT25QL256ABA-1EW7-OSIT flash
* memory from Micron and should work for similar devices from the same vendor.
*/
#ifndef __MT25QL_H__
#define __MT25QL_H__
#include "qspi_ip6514e_drv.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MT25QL Flash Memory documentation defined values.
*/
#define FLASH_PAGE_SIZE (256U) /* 256B */
#define SUBSECTOR_4KB (0x00001000U) /* 4KB */
#define SUBSECTOR_32KB (0x00008000U) /* 32KB */
#define SECTOR_64KB (0x00010000U) /* 64KB */
#define ADDR_BYTES (3U)
enum mt25ql_error_t {
MT25QL_ERR_NONE = QSPI_IP6514E_ERR_NONE,
MT25QL_ERR_WRONG_ARGUMENT = QSPI_IP6514E_ERR_WRONG_ARGUMENT,
MT25QL_ERR_CTRL_NOT_DISABLED = QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
MT25QL_ERR_READ_IN_PROGRESS = QSPI_IP6514E_ERR_READ_IN_PROGRESS,
MT25QL_ERR_WRITE_IN_PROGRESS = QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
MT25QL_ERR_ADDR_NOT_ALIGNED,
MT25QL_ERR_NOT_INITED,
MT25QL_ERR_ADDR_TOO_BIG,
};
enum mt25ql_erase_t {
MT25QL_ERASE_ALL_FLASH = 0U, /*!< Erase all flash */
MT25QL_ERASE_SUBSECTOR_4K = SUBSECTOR_4KB, /*!< Erase a 4 KB subsector */
MT25QL_ERASE_SUBSECTOR_32K = SUBSECTOR_32KB, /*!< Erase a 32 KB subsector */
MT25QL_ERASE_SECTOR_64K = SECTOR_64KB, /*!< Erase a sector (64 KB) */
};
enum mt25ql_functional_state_t {
MT25QL_FUNC_STATE_NOT_INITED = 0U,
/*!< QSPI Flash controller is not initialized, only direct read
* is guaranteed to be working
*/
MT25QL_FUNC_STATE_DEFAULT = 1U,
/*!< The QSPI Flash controller and memory is in default state,
* using basic read/write commands
*/
MT25QL_FUNC_STATE_FAST = 2U,
/*!< The QSPI Flash controller and memory is configured to operate in
* single SPI mode and fast Flash commands could be used for read and
* program operations.
*/
MT25QL_FUNC_STATE_QUAD_FAST = 3U,
/*!< The QSPI Flash controller and memory is configured to operate in
* Quad SPI mode and fast Flash commands could be used for read and
* program operations.
*/
};
struct mt25ql_config_state_t {
enum mt25ql_functional_state_t func_state;
/*!< Functional state id */
enum qspi_ip6514e_spi_mode_t spi_mode;
/*!< SPI mode for the current functional state */
uint8_t opcode_read;
/*!< Read opcode for the current functional state */
uint8_t opcode_write;
/*!< Write opcode for the current functional state */
uint32_t dummy_cycles_read;
/*!< Dummy cycles for the read command for the current functional state */
uint32_t dummy_cycles_write;
/*!< Dummy cycles for the write command for the current functional state */
};
struct mt25ql_dev_t {
struct qspi_ip6514e_dev_t *controller;
/*!< QSPI Flash controller. */
uint32_t direct_access_start_addr;
/*!< AHB address to directly access the contents of the Flash memory
* through the QSPI Controller.
*/
uint32_t baud_rate_div;
/*!< Clock divisor that will be used to configure the QSPI Flash
* Controller to access the Flash memory. The clock which frequency is
* divived is the one linked to the QSPI Flash controller. It can only
* be an even number between 2 and 32 (both included). It needs to be
* high enough to support the Quad Output Fast Read command with 8
* dummy cycles and the Quad Input Fast Program with 0 dummy cycles.
*/
uint32_t size; /*!< Total size of the MT25QL Flash memory */
struct mt25ql_config_state_t config_state;
/*!< Configured functional state (with parameter settings) of the
* QSPI Flash controller and memory.
*/
};
/**
* \brief Change configuration of the QSPI Flash controller and MT25QL memory
*
* Changes the configuration of the QSPI Flash controller and MT25QL
* Flash memory to operate in the specified SPI mode and to use the
* appropriate Flash commands for read and program operations.
* It also sets:
* + The number of dummy cycles for each operation
* + The bytes per page constant to 256 (MT25QL Flash specific)
* + The number of address bytes to 3
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] f_state Functional state to be set on flash controller
* and device \ref mt25ql_functional_state_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function assumes that the Flash memory device and the QSPI Flash
* controller operates with the same SPI protocol. This function will fail
* if the Flash device is in a different configuration.
*/
enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
enum mt25ql_functional_state_t f_state);
/**
* \brief Restore the QSPI Flash controller and MT25QL to reset state.
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function assumes that the Flash memory device and the QSPI Flash
* controller operates with the same SPI protocol. This function will fail
* if the Flash device is in a different configuration.
*/
enum mt25ql_error_t mt25ql_restore_reset_state(struct mt25ql_dev_t* dev);
/**
* \brief Read bytes from the flash memory (direct access)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the read operation
* \param[out] data Pointer where len bytes read from the flash memory will be
* written to
* \param[in] len Number of bytes to read
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use direct access to read from the Flash memory. It
* can be used to access above the direct accessible memory zone if
* not all the AHB address wires are connected.
* \note The address given should be the address of the data inside the flash
* memory. To read the first byte inside the memory, use 0x00000000.
*/
enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len);
/**
* \brief Write bytes in the flash memory, at a location where data has already
* been erased (direct access)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the write operation
* \param[in] data Pointer to the len bytes that will be written to the flash
* memory
* \param[in] len Number of bytes to write
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use direct access to write to the Flash memory. It
* can be used to access outside of the direct accessible memory zone if
* not all the AHB address wires are connected.
* \note The address given should be the address of the data inside the flash
* memory. To write the first byte inside the memory, use 0x00000000.
* \note Writing bytes in the flash memory clear them from 1 to 0, for that
* matter the location where data is written needs to be erased
* beforehand.
*/
enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len);
/**
* \brief Read bytes from the flash memory (using Flash commands)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the read operation
* \param[out] data Pointer where len bytes read from the flash memory will be
* written to
* \param[in] len Number of bytes to read
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use the Software Triggered Instruction Generator to
* read from the Flash memory using Flash commands.
* \note The address given should be the address of the data inside the flash
* memory. To read the first byte inside the memory, use 0x00000000.
*/
enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
uint32_t addr,
void *data,
uint32_t len);
/**
* \brief Write bytes in the flash memory, at a location where data has already
* been erased (using Flash commands)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Flash memory address for the write operation
* \param[in] data Pointer to the len bytes that will be written to the flash
* memory
* \param[in] len Number of bytes to write
*
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note This function will use the Software Triggered Instruction Generator to
* write to the Flash memory using Flash commands.
* \note The address given should be the address of the data inside the flash
* memory. To write the first byte inside the memory, use 0x00000000.
* \note Writing bytes in the flash memory clear them from 1 to 0, for that
* matter the location where data is written needs to be erased
* beforehand.
*/
enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
uint32_t addr,
const void *data,
uint32_t len);
/**
* \brief Erase all flash memory, a sector (64 KiB) or a subsector
* (32 KiB or 4 KiB)
*
* \param[in] dev Pointer to MT25QL device structure \ref mt25ql_dev_t
* \param[in] addr Address where to erase in the flash memory
* \param[in] erase_type Type of what to erase at the specified address:
* * whole flash memory
* * a subsector (4 KiB or 32 KiB)
* * a sector (64 KiB)
* \return Return error code as specified in \ref mt25ql_error_t
*
* \note The address need to be aligned with the size of what is erased or 0 if
* all flash memory is to be erased.
*/
enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
uint32_t addr,
enum mt25ql_erase_t erase_type);
#ifdef __cplusplus
}
#endif
#endif /* __MT25QL_H__ */

View File

@ -1,153 +0,0 @@
#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
/*
* Copyright (c) 2018-2020 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../../../partition/region_defs.h"
#if !defined(TFM_LVL)
#define TFM_LVL 1
#endif
#if !defined(MBED_ROM_START)
#define MBED_ROM_START S_CODE_START // 0x1A020400
#endif
#if !defined(MBED_ROM_SIZE)
#define MBED_ROM_SIZE IMAGE_S_CODE_SIZE // 0x4f800
#endif
#if !defined(MBED_RAM_START)
#define MBED_RAM_START S_DATA_START // 0x30000000
#endif
#if !defined(MBED_RAM_SIZE)
#define MBED_RAM_SIZE S_DATA_SIZE // 0x40000
#endif
LR_CODE MBED_ROM_START MBED_ROM_SIZE {
/**** This initial section contains common code for TEE */
ER_TFM_CODE MBED_ROM_START S_CODE_SIZE {
*.o (RESET +First)
.ANY (+RO)
}
#if TFM_LVL == 1
/* Shared area between BL2 and runtime to exchange data */
TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
}
/* MSP */
ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE {
}
/* PSP */
ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE {
}
ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE {
}
ER_TFM_DATA +0 {
.ANY (+RW +ZI)
}
TFM_SECURE_STACK +0 ALIGN 128 EMPTY 0x1000 {
}
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
#else /* TFM_LVL == 1 */
/**** Unprivileged Secure code start here */
TFM_UNPRIV_CODE +0 ALIGN 32 {
tfm_spm_services.o (+RO)
device_definition.o (+RO)
*(SFN)
*armlib*
}
TFM_SP_PLATFORM +0 ALIGN 32 {
*tfm_platform* (+RO)
*(TFM_SP_PLATFORM_ATTR_FN)
}
/* Shared area between BL2 and runtime to exchange data */
TFM_SHARED_DATA MBED_RAM_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
}
/* MSP */
ARM_LIB_STACK_MSP MBED_RAM_START ALIGN 32 OVERLAY EMPTY S_MSP_STACK_SIZE {
}
/* PSP */
ARM_LIB_STACK +0 ALIGN 32 EMPTY S_PSP_STACK_SIZE {
}
ARM_LIB_HEAP +0 ALIGN 8 EMPTY S_HEAP_SIZE {
}
ER_TFM_DATA +0 {
.ANY (+RW +ZI)
}
TFM_UNPRIV_RO_DATA +0 ALIGN 32 {
tfm_spm_services.o (+RW +ZI)
device_definition.o (+RW +ZI)
}
TFM_UNPRIV_SCRATCH +0 ALIGN 32 EMPTY 0x400 {
}
TFM_SP_PLATFORM_DATA +0 ALIGN 32 {
*tfm_platform* (+RW +ZI)
}
TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
}
#endif /* TFM_LVL == 1 */
/* This empty, zero long execution region is here to mark the limit address
* of the last execution region that is allocated in SRAM.
*/
SRAM_WATERMARK +0 EMPTY 0x0 {
}
ER_CODE_CMSE_VENEER CMSE_VENEER_REGION_START FIXED PADVALUE 0xFFFFFFFF CMSE_VENEER_REGION_SIZE {
*(Veneer$$CMSE)
}
/* Make sure that the sections allocated in the SRAM does not exceed the
* size of the SRAM available.
*/
ScatterAssert(ImageLimit(SRAM_WATERMARK) <= MBED_RAM_START + MBED_RAM_SIZE)
}
LR_NS_PARTITION NS_PARTITION_START {
/* Reserved place for NS application.
* No code will be placed here, just address of this region is used in the
* secure code to configure certain HW components.
*/
ER_NS_PARTITION NS_PARTITION_START EMPTY NS_PARTITION_SIZE {
}
}

View File

@ -1,291 +0,0 @@
;/*
; * Copyright (c) 2017-2020 ARM Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; */
;
; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s
; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
;/*
;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
;*/
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
IMPORT |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit|
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors ;Core Interrupts
DCD |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit| ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD SecureFault_Handler ; Secure Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
;SSE-200 Interrupts
DCD NS_WATCHDOG_RESET_IRQHandler ; 0: Non-Secure Watchdog Reset Request Interrupt
DCD NS_WATCHDOG_IRQHandler ; 1: Non-Secure Watchdog Interrupt
DCD S32K_TIMER_IRQHandler ; 2: S32K Timer Interrupt
DCD TIMER0_IRQHandler ; 3: CMSDK Timer 0 Interrupt
DCD TIMER1_IRQHandler ; 4: CMSDK Timer 1 Interrupt
DCD DUALTIMER_IRQHandler ; 5: CMSDK Dual Timer Interrupt
DCD MHU0_IRQHandler ; 6: Message Handling Unit 0 Interrupt
DCD MHU1_IRQHandler ; 7: Message Handling Unit 1 Interrupt
DCD CRYPTOCELL_IRQHandler ; 8: CryptoCell-312 Interrupt
DCD MPC_Handler ; 9: Secure Combined MPC Interrupt
DCD PPC_Handler ; 10: Secure Combined PPC Interrupt
DCD S_MSC_COMBINED_IRQHandler ; 11: Secure Combined MSC Interrupt
DCD S_BRIDGE_ERR_IRQHandler ; 12: Secure Bridge Error Combined Interrupt
DCD I_CACHE_INV_ERR_IRQHandler ; 13: Intsruction Cache Invalidation Interrupt
DCD 0 ; 14: Reserved
DCD SYS_PPU_IRQHandler ; 15: System PPU Interrupt
DCD CPU0_PPU_IRQHandler ; 16: CPU0 PPU Interrupt
DCD CPU1_PPU_IRQHandler ; 17: CPU1 PPU Interrupt
DCD CPU0_DGB_PPU_IRQHandler ; 18: CPU0 Debug PPU Interrupt
DCD CPU1_DGB_PPU_IRQHandler ; 19: CPU1 Debug PPU Interrupt
DCD 0 ; 20: Reserved
DCD 0 ; 21: Reserved
DCD RAM0_PPU_IRQHandler ; 22: RAM 0 PPU Interrupt
DCD RAM1_PPU_IRQHandler ; 23: RAM 1 PPU Interrupt
DCD RAM2_PPU_IRQHandler ; 24: RAM 2 PPU Interrupt
DCD RAM3_PPU_IRQHandler ; 25: RAM 3 PPU Interrupt
DCD DEBUG_PPU_IRQHandler ; 26: Debug PPU Interrupt
DCD 0 ; 27: Reserved
DCD CPUn_CTI_0_IRQHandler ; 28: CPUn CTI Interrupt 0
DCD CPUn_CTI_1_IRQHandler ; 29: CPUn CTI Interrupt 1
DCD 0 ; 30: Reserved
DCD 0 ; 31: Reserved
;Expansion Interrupts
DCD 0 ; 32: Reserved
DCD GpTimer_IRQHandler ; 33: General Purpose Timer
DCD I2C0_IRQHandler ; 34: I2C0
DCD I2C1_IRQHandler ; 35: I2C1
DCD I2S_IRQHandler ; 36: I2S
DCD SPI_IRQHandler ; 37: SPI
DCD QSPI_IRQHandler ; 38: QSPI
DCD UARTRX0_Handler ; 39: UART0 receive FIFO interrupt
DCD UARTTX0_Handler ; 40: UART0 transmit FIFO interrupt
DCD UART0_RxTimeout_IRQHandler ; 41: UART0 receive timeout interrupt
DCD UART0_ModemStatus_IRQHandler ; 42: UART0 modem status interrupt
DCD UART0_Error_IRQHandler ; 43: UART0 error interrupt
DCD UART0_IRQHandler ; 44: UART0 interrupt
DCD UARTRX1_Handler ; 45: UART0 receive FIFO interrupt
DCD UARTTX1_Handler ; 46: UART0 transmit FIFO interrupt
DCD UART1_RxTimeout_IRQHandler ; 47: UART0 receive timeout interrupt
DCD UART1_ModemStatus_IRQHandler ; 48: UART0 modem status interrupt
DCD UART1_Error_IRQHandler ; 49: UART0 error interrupt
DCD UART1_IRQHandler ; 50: UART0 interrupt
DCD GPIO_0_IRQHandler ; 51: GPIO 0 interrupt
DCD GPIO_1_IRQHandler ; 52: GPIO 1 interrupt
DCD GPIO_2_IRQHandler ; 53: GPIO 2 interrupt
DCD GPIO_3_IRQHandler ; 54: GPIO 3 interrupt
DCD GPIO_4_IRQHandler ; 55: GPIO 4 interrupt
DCD GPIO_5_IRQHandler ; 56: GPIO 5 interrupt
DCD GPIO_6_IRQHandler ; 57: GPIO 6 interrupt
DCD GPIO_7_IRQHandler ; 58: GPIO 7 interrupt
DCD GPIO_8_IRQHandler ; 59: GPIO 8 interrupt
DCD GPIO_9_IRQHandler ; 60: GPIO 9 interrupt
DCD GPIO_10_IRQHandler ; 61: GPIO 10 interrupt
DCD GPIO_11_IRQHandler ; 62: GPIO 11 interrupt
DCD GPIO_12_IRQHandler ; 63: GPIO 12 interrupt
DCD GPIO_13_IRQHandler ; 64: GPIO 13 interrupt
DCD GPIO_14_IRQHandler ; 65: GPIO 14 interrupt
DCD GPIO_15_IRQHandler ; 66: GPIO 15 interrupt
DCD GPIO_Combined_IRQHandler ; 67: GPIO Combined interrupt
DCD PVT_IRQHandler ; 68: PVT sensor interrupt
DCD 0 ; 69: Reserved
DCD PWM_0_IRQHandler ; 70: PWM0 interrupt
DCD RTC_IRQHandler ; 71: RTC interrupt
DCD GpTimer1_IRQHandler ; 72: General Purpose Timer1
DCD GpTimer0_IRQHandler ; 73: General Purpose Timer0
DCD PWM_1_IRQHandler ; 74: PWM1 interrupt
DCD PWM_2_IRQHandler ; 75: PWM2 interrupt
DCD GPIO_Combined_NS_IRQHandler ; 76: GPIO Combined Non-secure interrupt
DCD SDIO_IRQHandler ; 77: SDIO interrupt handler
DCD 0 ; 78: Reserved
DCD 0 ; 79: Reserved
DCD 0 ; 80: Reserved
DCD 0 ; 81: Reserved
DCD 0 ; 82: Reserved
DCD 0 ; 83: Reserved
DCD CryptoSS_Reset_Status_IRQHandler ; 84: Crypto SS reset status
DCD HostMHUS0_Int_Acc_NR2R_IRQHandler ; 85: MHU0 Sender IRQ not-ready to ready
DCD HostMHUS0_Int_Acc_R2NR_IRQHandler ; 86: MHU0 Sender IRQ ready to not ready
DCD HostMHUR0_IRQ_Reg0_IRQHandler ; 87: MHU0 Receiver IRQ Register 0
DCD HostMHUR0_IRQ_Reg1_IRQHandler ; 88: MHU0 Receiver IRQ Register 1
DCD HostMHUR0_IRQComb_IRQHandler ; 89: MHU0 Receiver IRQ combined
DCD HostMHUS1_Int_Acc_NR2R_IRQHandler ; 90: MHU1 Sender IRQ not-ready to ready
DCD HostMHUS1_Int_Acc_R2NR_IRQHandler ; 91: MHU1 Sender IRQ ready to not ready
DCD HostMHUR1_IRQ_Reg0_IRQHandler ; 92: MHU1 Receiver IRQ Register 0
DCD HostMHUR1_IRQ_Reg1_IRQHandler ; 93: MHU1 Receiver IRQ Register 1
DCD HostMHUR1_IRQComb_IRQHandler ; 94: MHU1 Receiver IRQ combined
DCD EFlash0_Controller_IRQHandler ; 95: GFC-100 EFlash 0 controller interrupt
DCD EFlash1_Controller_IRQHandler ; 96: GFC-100 EFlash 1 controller interrupt
DCD 0 ; 97:127 Reserved
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
; Reset Handler
AREA |.text|, CODE, READONLY
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
CPSID i ; Disable IRQs
LDR R0, =SystemInit
BLX R0
MRS R0, control ; Get control value
ORR R0, R0, #2 ; Select switch to PSP
MSR control, R0
LDR R0, =__main
BX R0
ENDP
End_Of_Main
B .
ALIGN 4
; Dummy Exception Handlers (infinite loops which can be modified)
MACRO
Default_Handler $handler_name
$handler_name PROC
EXPORT $handler_name [WEAK]
B .
ENDP
MEND
Default_Handler NMI_Handler
Default_Handler HardFault_Handler
Default_Handler MemManage_Handler
Default_Handler BusFault_Handler
Default_Handler UsageFault_Handler
Default_Handler SecureFault_Handler
Default_Handler SVC_Handler
Default_Handler DebugMon_Handler
Default_Handler PendSV_Handler
Default_Handler SysTick_Handler
Default_Handler NS_WATCHDOG_RESET_IRQHandler
Default_Handler NS_WATCHDOG_IRQHandler
Default_Handler S32K_TIMER_IRQHandler
Default_Handler TIMER0_IRQHandler
Default_Handler TIMER1_IRQHandler
Default_Handler DUALTIMER_IRQHandler
Default_Handler MHU0_IRQHandler
Default_Handler MHU1_IRQHandler
Default_Handler CRYPTOCELL_IRQHandler
Default_Handler MPC_Handler
Default_Handler PPC_Handler
Default_Handler S_MSC_COMBINED_IRQHandler
Default_Handler S_BRIDGE_ERR_IRQHandler
Default_Handler I_CACHE_INV_ERR_IRQHandler
Default_Handler SYS_PPU_IRQHandler
Default_Handler CPU0_PPU_IRQHandler
Default_Handler CPU1_PPU_IRQHandler
Default_Handler CPU0_DGB_PPU_IRQHandler
Default_Handler CPU1_DGB_PPU_IRQHandler
Default_Handler RAM0_PPU_IRQHandler
Default_Handler RAM1_PPU_IRQHandler
Default_Handler RAM2_PPU_IRQHandler
Default_Handler RAM3_PPU_IRQHandler
Default_Handler DEBUG_PPU_IRQHandler
Default_Handler CPUn_CTI_0_IRQHandler
Default_Handler CPUn_CTI_1_IRQHandler
Default_Handler GpTimer_IRQHandler
Default_Handler I2C0_IRQHandler
Default_Handler I2C1_IRQHandler
Default_Handler I2S_IRQHandler
Default_Handler SPI_IRQHandler
Default_Handler QSPI_IRQHandler
Default_Handler UARTRX0_Handler
Default_Handler UARTTX0_Handler
Default_Handler UART0_RxTimeout_IRQHandler
Default_Handler UART0_ModemStatus_IRQHandler
Default_Handler UART0_Error_IRQHandler
Default_Handler UART0_IRQHandler
Default_Handler UARTRX1_Handler
Default_Handler UARTTX1_Handler
Default_Handler UART1_RxTimeout_IRQHandler
Default_Handler UART1_ModemStatus_IRQHandler
Default_Handler UART1_Error_IRQHandler
Default_Handler UART1_IRQHandler
Default_Handler GPIO_0_IRQHandler
Default_Handler GPIO_1_IRQHandler
Default_Handler GPIO_2_IRQHandler
Default_Handler GPIO_3_IRQHandler
Default_Handler GPIO_4_IRQHandler
Default_Handler GPIO_5_IRQHandler
Default_Handler GPIO_6_IRQHandler
Default_Handler GPIO_7_IRQHandler
Default_Handler GPIO_8_IRQHandler
Default_Handler GPIO_9_IRQHandler
Default_Handler GPIO_10_IRQHandler
Default_Handler GPIO_11_IRQHandler
Default_Handler GPIO_12_IRQHandler
Default_Handler GPIO_13_IRQHandler
Default_Handler GPIO_14_IRQHandler
Default_Handler GPIO_15_IRQHandler
Default_Handler GPIO_Combined_IRQHandler
Default_Handler PVT_IRQHandler
Default_Handler PWM_0_IRQHandler
Default_Handler RTC_IRQHandler
Default_Handler GpTimer1_IRQHandler
Default_Handler GpTimer0_IRQHandler
Default_Handler PWM_1_IRQHandler
Default_Handler PWM_2_IRQHandler
Default_Handler GPIO_Combined_NS_IRQHandler
Default_Handler SDIO_IRQHandler
Default_Handler CryptoSS_Reset_Status_IRQHandler
Default_Handler HostMHUS0_Int_Acc_NR2R_IRQHandler
Default_Handler HostMHUS0_Int_Acc_R2NR_IRQHandler
Default_Handler HostMHUR0_IRQ_Reg0_IRQHandler
Default_Handler HostMHUR0_IRQ_Reg1_IRQHandler
Default_Handler HostMHUR0_IRQComb_IRQHandler
Default_Handler HostMHUS1_Int_Acc_NR2R_IRQHandler
Default_Handler HostMHUS1_Int_Acc_R2NR_IRQHandler
Default_Handler HostMHUR1_IRQ_Reg0_IRQHandler
Default_Handler HostMHUR1_IRQ_Reg1_IRQHandler
Default_Handler HostMHUR1_IRQComb_IRQHandler
Default_Handler EFlash0_Controller_IRQHandler
Default_Handler EFlash1_Controller_IRQHandler
ALIGN
END

View File

@ -1,366 +0,0 @@
;/*
; * Copyright (c) 2018-2020 ARM Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; *
; * This file is derivative of CMSIS V5.00 gcc_arm.ld
; */
/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
/* Linker script to configure memory regions. */
/* This file will be run trough the pre-processor. */
#include "../../../partition/region_defs.h"
#if !defined(TFM_LVL)
#define TFM_LVL 1
#endif
MEMORY
{
FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
RAM (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
VENEERS (rx) : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE
}
HEAP_SIZE = S_HEAP_SIZE;
__heap_size__ = S_HEAP_SIZE;
__psp_stack_size__ = S_PSP_STACK_SIZE;
__msp_init_stack_size__ = S_MSP_STACK_SIZE;
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a libc_nano.a)
ENTRY(Reset_Handler)
SECTIONS
{
.TFM_VECTORS : ALIGN(4)
{
__vectors_start__ = .;
KEEP(*(.vectors))
*startup*(.text*)
. = ALIGN(4);
__vectors_end__ = .;
} > FLASH
#if TFM_LVL == 1
.copy.table : ALIGN(4)
{
__copy_table_start__ = .;
LONG (LOADADDR(.TFM_DATA))
LONG (ADDR(.TFM_DATA))
LONG (SIZEOF(.TFM_DATA))
__copy_table_end__ = .;
} > FLASH
.zero.table : ALIGN(4)
{
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
LONG (ADDR(.TFM_SECURE_STACK))
LONG (SIZEOF(.TFM_SECURE_STACK))
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
} > FLASH
#else /* TFM_LVL == 1 */
.copy.table : ALIGN(4)
{
__copy_table_start__ = .;
LONG (LOADADDR(.TFM_DATA))
LONG (ADDR(.TFM_DATA))
LONG (SIZEOF(.TFM_DATA))
LONG (LOADADDR(.TFM_UNPRIV_RO_DATA))
LONG (ADDR(.TFM_UNPRIV_RO_DATA))
LONG (SIZEOF(.TFM_UNPRIV_RO_DATA))
LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
LONG (ADDR(.TFM_SP_PLATFORM_DATA))
LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
__copy_table_end__ = .;
} > FLASH
.zero.table : ALIGN(4)
{
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS))
LONG (ADDR(.TFM_UNPRIV_RO_BSS))
LONG (SIZEOF(.TFM_UNPRIV_RO_BSS))
LONG (ADDR(.TFM_SP_PLATFORM_BSS))
LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
LONG (ADDR(.TFM_SP_PLATFORM_STACK))
LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
} > FLASH
.TFM_UNPRIV_CODE : ALIGN(32)
{
*libc_nano*:*(.text*)
*libc_nano*:*(.rodata*)
*tfm_spm_services.o(.text*)
*tfm_spm_services.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
*libgcc*:*(.text*)
*libgcc*:*(.rodata*)
. = ALIGN(32);
} > FLASH
Image$$TFM_UNPRIV_CODE$$RO$$Base = ADDR(.TFM_UNPRIV_CODE);
Image$$TFM_UNPRIV_CODE$$RO$$Limit = ADDR(.TFM_UNPRIV_CODE) + SIZEOF(.TFM_UNPRIV_CODE);
.TFM_SP_PLATFORM : ALIGN(32)
{
*tfm_platform*:*(.text*)
*tfm_platform*:*(.rodata*)
*(TFM_SP_PLATFORM_ATTR_FN)
. = ALIGN(32);
} > FLASH
Image$$TFM_SP_PLATFORM$$RO$$Base = ADDR(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$RO$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
.ARM.extab : ALIGN(32)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
#endif /* TFM_LVL == 1 */
.ER_TFM_CODE :
{
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
OVERLAY S_DATA_START :
{
/* shared_data and msp_stack are overlapping on purpose when
* msp_stack is extended until the beginning of RAM, when shared_date
* was read out by partitions
*/
.tfm_bl2_shared_data
{
. = ALIGN(32);
. += BOOT_TFM_SHARED_DATA_SIZE;
}
.msp_stack
{
. = ALIGN(32);
. += S_MSP_STACK_SIZE;
}
} > RAM
Image$$ARM_LIB_STACK_MSP$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
.psp_stack :
{
. = ALIGN(32);
. += S_PSP_STACK_SIZE;
} > RAM
Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.psp_stack);
Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.psp_stack) + SIZEOF(.psp_stack);
#if TFM_LVL == 1
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += S_HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > RAM
Image$$ARM_LIB_HEAP$$ZI$$Base = ADDR(.heap);
Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
.TFM_SECURE_STACK :
{
. = ALIGN(128);
. += 0x1000;
} > RAM
Image$$TFM_SECURE_STACK$$ZI$$Base = ADDR(.TFM_SECURE_STACK);
Image$$TFM_SECURE_STACK$$ZI$$Limit = ADDR(.TFM_SECURE_STACK) + SIZEOF(.TFM_SECURE_STACK);
.TFM_UNPRIV_SCRATCH :
{
. = ALIGN(32);
. += 0x400;
} > RAM
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
#else /* TFM_LVL == 1 */
.TFM_UNPRIV_RO_DATA :
{
*/tfm_spm_services.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$RW$$Base = ADDR(.TFM_UNPRIV_RO_DATA);
Image$$TFM_UNPRIV_RO_DATA$$RW$$Limit = ADDR(.TFM_UNPRIV_RO_DATA) + SIZEOF(.TFM_UNPRIV_RO_DATA);
.TFM_UNPRIV_RO_BSS : ALIGN(32)
{
*/tfm_spm_services.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/tfm_spm_services.o(COMMON)
*/platform_retarget_dev.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Limit = ADDR(.TFM_UNPRIV_RO_BSS) + SIZEOF(.TFM_UNPRIV_RO_BSS);
.TFM_UNPRIV_SCRATCH : ALIGN(32)
{
. += 0x400;
} > RAM AT> FLASH
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Base = ADDR(.TFM_UNPRIV_SCRATCH);
Image$$TFM_UNPRIV_SCRATCH$$ZI$$Limit = ADDR(.TFM_UNPRIV_SCRATCH) + SIZEOF(.TFM_UNPRIV_SCRATCH);
.TFM_SP_PLATFORM_DATA : ALIGN(32)
{
*tfm_platform*:*(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_DATA$$RW$$Base = ADDR(.TFM_SP_PLATFORM_DATA);
Image$$TFM_SP_PLATFORM_DATA$$RW$$Limit = ADDR(.TFM_SP_PLATFORM_DATA) + SIZEOF(.TFM_SP_PLATFORM_DATA);
.TFM_SP_PLATFORM_BSS : ALIGN(32)
{
*tfm_platform*:*(.bss*)
*tfm_platform*:*(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_BSS);
Image$$TFM_SP_PLATFORM_DATA$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_BSS) + SIZEOF(.TFM_SP_PLATFORM_BSS);
.TFM_SP_PLATFORM_STACK : ALIGN(128)
{
. += 0x0400;
} > RAM AT> FLASH
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
#endif /* TFM_LVL == 1 */
.TFM_DATA :
{
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
} > RAM AT> FLASH
Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
ASSERT(Image$$ER_TFM_DATA$$Limit <= S_DATA_START + S_DATA_SIZE, "Exceeding secure RAM")
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
* separate 32 bytes aligned region so that the SAU can programmed to just set
* this region as Non-Secure Callable.
*/
.gnu.sgstubs : ALIGN(32)
{
*(.gnu.sgstubs*)
. = ALIGN(32);
} > VENEERS AT> VENEERS
Image$$ER_CODE_CMSE_VENEER$$Base = ADDR(.gnu.sgstubs);
Image$$ER_CODE_CMSE_VENEER$$Limit = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs);
Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
PROVIDE(__StackTop = __stack);
PROVIDE(__StackLimit = __StackTop - SIZEOF(.psp_stack));
}

View File

@ -1,401 +0,0 @@
;/*
; * Copyright (c) 2009-2020 Arm Limited
; *
; * SPDX-License-Identifier: Apache-2.0
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; *
; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S
; */
.syntax unified
.arch armv8-m.main
.section .vectors
.align 2
.globl __Vectors
__Vectors:
.long Image$$ARM_LIB_STACK_MSP$$ZI$$Limit /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long MemManage_Handler /* MPU Fault Handler */
.long BusFault_Handler /* Bus Fault Handler */
.long UsageFault_Handler /* Usage Fault Handler */
.long SecureFault_Handler /* Secure Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long DebugMon_Handler /* Debug Monitor Handler */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* Core interrupts */
.long NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */
.long NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */
.long S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */
.long TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */
.long TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */
.long DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */
.long MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */
.long MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */
.long CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */
.long MPC_Handler /* 9: Secure Combined MPC Interrupt */
.long PPC_Handler /* 10: Secure Combined PPC Interrupt */
.long S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */
.long S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */
.long I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */
.long 0 /* 14: Reserved */
.long SYS_PPU_IRQHandler /* 15: System PPU Interrupt */
.long CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */
.long CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */
.long CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */
.long CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */
.long 0 /* 20: Reserved */
.long 0 /* 21: Reserved */
.long RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */
.long RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */
.long RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */
.long RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */
.long DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */
.long 0 /* 27: Reserved */
.long CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */
.long CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */
.long 0 /* 30: Reserved */
.long 0 /* 31: Reserved */
/* External interrupts */
.long 0 /* 32: Reserved */
.long GpTimer_IRQHandler /* 33: General Purpose Timer */
.long I2C0_IRQHandler /* 34: I2C0 */
.long I2C1_IRQHandler /* 35: I2C1 */
.long I2S_IRQHandler /* 36: I2S */
.long SPI_IRQHandler /* 37: SPI */
.long QSPI_IRQHandler /* 38: QSPI */
.long UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */
.long UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */
.long UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */
.long UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */
.long UART0_Error_IRQHandler /* 43: UART0 error interrupt */
.long UART0_IRQHandler /* 44: UART0 interrupt */
.long UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */
.long UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */
.long UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */
.long UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */
.long UART1_Error_IRQHandler /* 49: UART0 error interrupt */
.long UART1_IRQHandler /* 50: UART0 interrupt */
.long GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */
.long GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */
.long GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */
.long GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */
.long GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */
.long GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */
.long GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */
.long GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */
.long GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */
.long GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */
.long GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */
.long GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */
.long GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */
.long GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */
.long GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */
.long GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */
.long GPIO_Combined_IRQHandler /* 67: GPIO Combined interrupt */
.long PVT_IRQHandler /* 68: PVT sensor interrupt */
.long 0 /* 69: Reserved */
.long PWM_0_IRQHandler /* 70: PWM0 interrupt */
.long RTC_IRQHandler /* 71: RTC interrupt */
.long GpTimer0_IRQHandler /* 72: General Purpose Timer0 */
.long GpTimer1_IRQHandler /* 73: General Purpose Timer1 */
.long PWM_1_IRQHandler /* 74: PWM1 interrupt */
.long PWM_2_IRQHandler /* 75: PWM2 interrupt */
.long GPIO_Combined_NS_IRQHandler /* 76: GPIO Combined Non-secure interrupt */
.long SDIO_IRQHandler /* 77: SDIO interrupt handler */
.long 0 /* 78 Reserved */
.long 0 /* 79 Reserved */
.long 0 /* 80 Reserved */
.long 0 /* 81 Reserved */
.long 0 /* 82 Reserved */
.long 0 /* 83 Reserved */
.long CryptoSS_Reset_Status_IRQHandler /* 84: Crypto SS reset status */
.long HostMHUS0_Int_Acc_NR2R_IRQHandler /* 85: MHU0 Sender IRQ not-ready to ready */
.long HostMHUS0_Int_Acc_R2NR_IRQHandler /* 86: MHU0 Sender IRQ ready to not ready */
.long HostMHUR0_IRQ_Reg0_IRQHandler /* 87: MHU0 Receiver IRQ Register 0 */
.long HostMHUR0_IRQ_Reg1_IRQHandler /* 88: MHU0 Receiver IRQ Register 1 */
.long HostMHUR0_IRQComb_IRQHandler /* 89: MHU0 Receiver IRQ combined */
.long HostMHUS1_Int_Acc_NR2R_IRQHandler /* 90: MHU1 Sender IRQ not-ready to ready */
.long HostMHUS1_Int_Acc_R2NR_IRQHandler /* 91: MHU1 Sender IRQ ready to not ready */
.long HostMHUR1_IRQ_Reg0_IRQHandler /* 92: MHU1 Receiver IRQ Register 0 */
.long HostMHUR1_IRQ_Reg1_IRQHandler /* 93: MHU1 Receiver IRQ Register 1 */
.long HostMHUR1_IRQComb_IRQHandler /* 94: MHU1 Receiver IRQ combined */
.long EFlash0_Controller_IRQHandler /* 95: GFC-100 EFlash 0 controller interrupt */
.long EFlash1_Controller_IRQHandler /* 96: GFC-100 EFlash 1 controller interrupt */
.long 0 /* 97:127 Reserved */
.size __Vectors, . - __Vectors
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Firstly it copies data from read only memory to RAM. There are two schemes
* to copy. One can copy more than one sections. Another can only copy
* one section. The former scheme needs more instructions and read-only
* data to implement than the latter.
* Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
#ifdef __STARTUP_COPY_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of triplets, each of which specify:
* offset 0: LMA of start of a section to copy from
* offset 4: VMA of start of a section to copy to
* offset 8: size of the section to copy. Must be multiply of 4
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r4, =__copy_table_start__
ldr r5, =__copy_table_end__
.L_loop0:
cmp r4, r5
bge .L_loop0_done
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]
.L_loop0_0:
subs r3, #4
ittt ge
ldrge r0, [r1, r3]
strge r0, [r2, r3]
bge .L_loop0_0
adds r4, #12
b .L_loop0
.L_loop0_done:
#else
/* Single section scheme.
*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
.L_loop1:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .L_loop1
#endif /*__STARTUP_COPY_MULTIPLE */
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* There are two schemes too. One can clear multiple BSS sections. Another
* can only clear one section. The former is more size expensive than the
* latter.
*
* Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
* Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
*/
#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of tuples specifying:
* offset 0: Start of a BSS section
* offset 4: Size of this BSS section. Must be multiply of 4
*/
ldr r3, =__zero_table_start__
ldr r4, =__zero_table_end__
.L_loop2:
cmp r3, r4
bge .L_loop2_done
ldr r1, [r3]
ldr r2, [r3, #4]
movs r0, 0
.L_loop2_0:
subs r2, #4
itt ge
strge r0, [r1, r2]
bge .L_loop2_0
adds r3, #8
b .L_loop2
.L_loop2_done:
#elif defined (__STARTUP_CLEAR_BSS)
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.L_loop3:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .L_loop3
#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
cpsid i /* Disable IRQs */
bl SystemInit
mrs r0, control /* Get control value */
orr r0, r0, #2 /* Select switch to PSP */
msr control, r0
ldr r0, =Image$$ARM_LIB_STACK$$ZI$$Limit
msr psp, r0
#ifndef __START
#define __START _start
#endif
bl __START
.pool
.size Reset_Handler, . - Reset_Handler
/* Macro to define default handlers. */
.macro def_irq_handler handler_name
.align 1
.thumb_func
.weak \handler_name
\handler_name:
b \handler_name
.endm
def_irq_handler NMI_Handler
def_irq_handler HardFault_Handler
def_irq_handler MemManage_Handler
def_irq_handler BusFault_Handler
def_irq_handler UsageFault_Handler
def_irq_handler SecureFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
/* Core interrupts */
def_irq_handler NS_WATCHDOG_RESET_IRQHandler /* 0: Non-Secure Watchdog Reset Request Interrupt */
def_irq_handler NS_WATCHDOG_IRQHandler /* 1: Non-Secure Watchdog Interrupt */
def_irq_handler S32K_TIMER_IRQHandler /* 2: S32K Timer Interrupt */
def_irq_handler TIMER0_IRQHandler /* 3: CMSDK Timer 0 Interrupt */
def_irq_handler TIMER1_IRQHandler /* 4: CMSDK Timer 1 Interrupt */
def_irq_handler DUALTIMER_IRQHandler /* 5: CMSDK Dual Timer Interrupt */
def_irq_handler MHU0_IRQHandler /* 6: Message Handling Unit 0 Interrupt */
def_irq_handler MHU1_IRQHandler /* 7: Message Handling Unit 1 Interrupt */
def_irq_handler CRYPTOCELL_IRQHandler /* 8: CryptoCell-312 Interrupt */
def_irq_handler MPC_Handler /* 9: Secure Combined MPC Interrupt */
def_irq_handler PPC_Handler /* 10: Secure Combined PPC Interrupt */
def_irq_handler S_MSC_COMBINED_IRQHandler /* 11: Secure Combined MSC Interrupt */
def_irq_handler S_BRIDGE_ERR_IRQHandler /* 12: Secure Bridge Error Combined Interrupt */
def_irq_handler I_CACHE_INV_ERR_IRQHandler /* 13: Intsruction Cache Invalidation Interrupt */
def_irq_handler SYS_PPU_IRQHandler /* 15: System PPU Interrupt */
def_irq_handler CPU0_PPU_IRQHandler /* 16: CPU0 PPU Interrupt */
def_irq_handler CPU1_PPU_IRQHandler /* 17: CPU1 PPU Interrupt */
def_irq_handler CPU0_DGB_PPU_IRQHandler /* 18: CPU0 Debug PPU Interrupt */
def_irq_handler CPU1_DGB_PPU_IRQHandler /* 19: CPU1 Debug PPU Interrupt */
def_irq_handler RAM0_PPU_IRQHandler /* 22: RAM 0 PPU Interrupt */
def_irq_handler RAM1_PPU_IRQHandler /* 23: RAM 1 PPU Interrupt */
def_irq_handler RAM2_PPU_IRQHandler /* 24: RAM 2 PPU Interrupt */
def_irq_handler RAM3_PPU_IRQHandler /* 25: RAM 3 PPU Interrupt */
def_irq_handler DEBUG_PPU_IRQHandler /* 26: Debug PPU Interrupt */
def_irq_handler CPU0_CTI_IRQHandler /* 28: CPU0 CTI Interrupt */
def_irq_handler CPU1_CTI_IRQHandler /* 29: CPU1 CTI Interrupt */
/* External interrupts */
def_irq_handler GpTimer_IRQHandler /* 33: General Purpose Timer */
def_irq_handler I2C0_IRQHandler /* 34: I2C0 */
def_irq_handler I2C1_IRQHandler /* 35: I2C1 */
def_irq_handler I2S_IRQHandler /* 36: I2S */
def_irq_handler SPI_IRQHandler /* 37: SPI */
def_irq_handler QSPI_IRQHandler /* 38: QSPI */
def_irq_handler UARTRX0_Handler /* 39: UART0 receive FIFO interrupt */
def_irq_handler UARTTX0_Handler /* 40: UART0 transmit FIFO interrupt */
def_irq_handler UART0_RxTimeout_IRQHandler /* 41: UART0 receive timeout interrupt */
def_irq_handler UART0_ModemStatus_IRQHandler /* 42: UART0 modem status interrupt */
def_irq_handler UART0_Error_IRQHandler /* 43: UART0 error interrupt */
def_irq_handler UART0_IRQHandler /* 44: UART0 interrupt */
def_irq_handler UARTRX1_Handler /* 45: UART0 receive FIFO interrupt */
def_irq_handler UARTTX1_Handler /* 46: UART0 transmit FIFO interrupt */
def_irq_handler UART1_RxTimeout_IRQHandler /* 47: UART0 receive timeout interrupt */
def_irq_handler UART1_ModemStatus_IRQHandler /* 48: UART0 modem status interrupt */
def_irq_handler UART1_Error_IRQHandler /* 49: UART0 error interrupt */
def_irq_handler UART1_IRQHandler /* 50: UART0 interrupt */
def_irq_handler GPIO_0_IRQHandler /* 51: GPIO 0 interrupt */
def_irq_handler GPIO_1_IRQHandler /* 52: GPIO 1 interrupt */
def_irq_handler GPIO_2_IRQHandler /* 53: GPIO 2 interrupt */
def_irq_handler GPIO_3_IRQHandler /* 54: GPIO 3 interrupt */
def_irq_handler GPIO_4_IRQHandler /* 55: GPIO 4 interrupt */
def_irq_handler GPIO_5_IRQHandler /* 56: GPIO 5 interrupt */
def_irq_handler GPIO_6_IRQHandler /* 57: GPIO 6 interrupt */
def_irq_handler GPIO_7_IRQHandler /* 58: GPIO 7 interrupt */
def_irq_handler GPIO_8_IRQHandler /* 59: GPIO 8 interrupt */
def_irq_handler GPIO_9_IRQHandler /* 60: GPIO 9 interrupt */
def_irq_handler GPIO_10_IRQHandler /* 61: GPIO 10 interrupt */
def_irq_handler GPIO_11_IRQHandler /* 62: GPIO 11 interrupt */
def_irq_handler GPIO_12_IRQHandler /* 63: GPIO 12 interrupt */
def_irq_handler GPIO_13_IRQHandler /* 64: GPIO 13 interrupt */
def_irq_handler GPIO_14_IRQHandler /* 65: GPIO 14 interrupt */
def_irq_handler GPIO_15_IRQHandler /* 66: GPIO 15 interrupt */
def_irq_handler GPIO_Combined_IRQHandler /* 67: GPIO Combined interrupt */
def_irq_handler PVT_IRQHandler /* 68: PVT sensor interrupt */
def_irq_handler PWM_0_IRQHandler /* 70: PWM0 interrupt */
def_irq_handler RTC_IRQHandler /* 71: RTC interrupt */
def_irq_handler GpTimer1_IRQHandler /* 72: General Purpose Timer0 */
def_irq_handler GpTimer0_IRQHandler /* 73: General Purpose Timer1 */
def_irq_handler PWM_1_IRQHandler /* 74: PWM1 interrupt */
def_irq_handler PWM_2_IRQHandler /* 75: PWM2 interrupt */
def_irq_handler GPIO_Combined_NS_IRQHandler /* 76: GPIO Combined Non-secure interrupt */
def_irq_handler SDIO_IRQHandler /* 77: SDIO interrupt handler */
def_irq_handler CryptoSS_Reset_Status_IRQHandler /* 84: Crypto SS reset status */
def_irq_handler HostMHUS0_Int_Acc_NR2R_IRQHandler /* 85: MHU0 Sender IRQ not-ready to ready */
def_irq_handler HostMHUS0_Int_Acc_R2NR_IRQHandler /* 86: MHU0 Sender IRQ ready to not ready */
def_irq_handler HostMHUR0_IRQ_Reg0_IRQHandler /* 87: MHU0 Receiver IRQ Register 0 */
def_irq_handler HostMHUR0_IRQ_Reg1_IRQHandler /* 88: MHU0 Receiver IRQ Register 1 */
def_irq_handler HostMHUR0_IRQComb_IRQHandler /* 89: MHU0 Receiver IRQ combined */
def_irq_handler HostMHUS1_Int_Acc_NR2R_IRQHandler /* 90: MHU1 Sender IRQ not-ready to ready */
def_irq_handler HostMHUS1_Int_Acc_R2NR_IRQHandler /* 91: MHU1 Sender IRQ ready to not ready */
def_irq_handler HostMHUR1_IRQ_Reg0_IRQHandler /* 92: MHU1 Receiver IRQ Register 0 */
def_irq_handler HostMHUR1_IRQ_Reg1_IRQHandler /* 93: MHU1 Receiver IRQ Register 1 */
def_irq_handler HostMHUR1_IRQComb_IRQHandler /* 94: MHU1 Receiver IRQ combined */
def_irq_handler EFlash0_Controller_IRQHandler /* 95: GFC-100 EFlash 0 controller interrupt */
def_irq_handler EFlash1_Controller_IRQHandler /* 96: GFC-100 EFlash 1 controller interrupt */
.end

View File

@ -1,791 +0,0 @@
/*
* Copyright (c) 2016-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mpc_sie_drv.h"
#include <stddef.h>
#include <stdbool.h>
#include "cmsis_compiler.h"
/* Values for hardware version in PIDR0 reg */
#define SIE200 0x60
#define SIE300 0x65
#define MPC_SIE_BLK_CFG_OFFSET 5U
/* Defines with numbering (eg: SIE300) are only relevant to the given SIE
* version. Defines without the numbering are applicable to all SIE versions.
*/
/* CTRL register bit indexes */
#define MPC_SIE200_CTRL_SEC_RESP (1UL << 4UL) /* MPC fault triggers a
* bus error
*/
#define MPC_SIE300_CTRL_GATE_REQ (1UL << 6UL) /* Request for gating
* incoming transfers
*/
#define MPC_SIE300_CTRL_GATE_ACK (1UL << 7UL) /* Acknowledge for gating
* incoming transfers
*/
#define MPC_SIE_CTRL_AUTOINCREMENT (1UL << 8UL) /* BLK_IDX auto increment */
#define MPC_SIE300_CTRL_SEC_RESP (1UL << 16UL) /* Response type when SW
* asks to gate the transfer
*/
#define MPC_SIE300_CTRL_GATE_PRESENT (1UL << 23UL) /* Gating feature present */
#define MPC_SIE_CTRL_SEC_LOCK_DOWN (1UL << 31UL) /* MPC Security lock down */
/* PIDR register bit masks */
#define MPC_PIDR0_SIE_VERSION_MASK ((1UL << 8UL) - 1UL)
/* ARM MPC interrupt */
#define MPC_SIE_INT_BIT (1UL)
/* Error code returned by the internal driver functions */
enum mpc_sie_intern_error_t {
MPC_SIE_INTERN_ERR_NONE = MPC_SIE_ERR_NONE,
MPC_SIE_INTERN_ERR_NOT_IN_RANGE = MPC_SIE_ERR_NOT_IN_RANGE,
MPC_SIE_INTERN_ERR_NOT_ALIGNED = MPC_SIE_ERR_NOT_ALIGNED,
MPC_SIE_INTERN_ERR_INVALID_RANGE = MPC_SIE_ERR_INVALID_RANGE,
MPC_INTERN_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE =
MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE,
/* Calculated block index
* is higher than the maximum allowed by the MPC. It should never
* happen unless the controlled ranges of the MPC are misconfigured
* in the driver or if the IP has not enough LUTs to cover the
* range, due to wrong reported block size for example.
*/
MPC_SIE_INTERN_ERR_BLK_IDX_TOO_HIGH = -1,
};
/* ARM MPC memory mapped register access structure */
struct mpc_sie_reg_map_t {
volatile uint32_t ctrl; /* (R/W) MPC Control */
volatile uint32_t reserved[3];/* Reserved */
volatile uint32_t blk_max; /* (R/ ) Maximum value of block based index */
volatile uint32_t blk_cfg; /* (R/ ) Block configuration */
volatile uint32_t blk_idx; /* (R/W) Index value for accessing block
* based look up table
*/
volatile uint32_t blk_lutn; /* (R/W) Block based gating
* Look Up Table (LUT)
*/
volatile uint32_t int_stat; /* (R/ ) Interrupt state */
volatile uint32_t int_clear; /* ( /W) Interrupt clear */
volatile uint32_t int_en; /* (R/W) Interrupt enable */
volatile uint32_t int_info1; /* (R/ ) Interrupt information 1 */
volatile uint32_t int_info2; /* (R/ ) Interrupt information 2 */
volatile uint32_t int_set; /* ( /W) Interrupt set. Debug purpose only */
volatile uint32_t reserved2[998]; /* Reserved */
volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */
volatile uint32_t pidr5; /* (R/ ) Peripheral ID 5 */
volatile uint32_t pidr6; /* (R/ ) Peripheral ID 6 */
volatile uint32_t pidr7; /* (R/ ) Peripheral ID 7 */
volatile uint32_t pidr0; /* (R/ ) Peripheral ID 0 */
volatile uint32_t pidr1; /* (R/ ) Peripheral ID 1 */
volatile uint32_t pidr2; /* (R/ ) Peripheral ID 2 */
volatile uint32_t pidr3; /* (R/ ) Peripheral ID 3 */
volatile uint32_t cidr0; /* (R/ ) Component ID 0 */
volatile uint32_t cidr1; /* (R/ ) Component ID 1 */
volatile uint32_t cidr2; /* (R/ ) Component ID 2 */
volatile uint32_t cidr3; /* (R/ ) Component ID 3 */
};
/*
* Checks if the address is controlled by the MPC and returns
* the range index in which it is contained.
*
* \param[in] dev MPC device to initialize \ref mpc_sie_dev_t
* \param[in] addr Address to check if it is controlled by MPC.
* \param[out] addr_range Range index in which it is contained.
*
* \return True if the base is controller by the range list, false otherwise.
*/
static uint32_t is_ctrl_by_range_list(
struct mpc_sie_dev_t* dev,
uint32_t addr,
const struct mpc_sie_memory_range_t** addr_range)
{
uint32_t i;
const struct mpc_sie_memory_range_t* range;
for(i = 0; i < dev->data->nbr_of_ranges; i++) {
range = dev->data->range_list[i];
if(addr >= range->base && addr <= range->limit) {
*addr_range = range;
return 1;
}
}
return 0;
}
/*
* Gets the masks selecting the bits in the LUT of the MPC corresponding
* to the base address (included) up to the limit address (included)
*
* \param[in] mpc_dev The MPC device.
* \param[in] base Address in a range controlled by this MPC
* (included), aligned on block size.
* \param[in] limit Address in a range controlled by this MPC
* (included), aligned on block size.
* \param[out] range Memory range in which the base address and
* limit are.
* \param[out] first_word_idx Index of the first touched word in the LUT.
* \param[out] nr_words Number of words used in the LUT. If 1, only
* first_word_mask is valid and limit_word_mask
* must not be used.
* \param[out] first_word_mask First word mask in the LUT will be stored here.
* \param[out] limit_word_mask Limit word mask in the LUT will be stored here.
*
* \return Returns error code as specified in \ref mpc_sie_intern_error_t
*/
static enum mpc_sie_intern_error_t get_lut_masks(
struct mpc_sie_dev_t* dev,
const uint32_t base, const uint32_t limit,
const struct mpc_sie_memory_range_t** range,
uint32_t *first_word_idx,
uint32_t *nr_words,
uint32_t *first_word_mask,
uint32_t *limit_word_mask)
{
const struct mpc_sie_memory_range_t* base_range;
uint32_t block_size;
uint32_t base_block_idx;
uint32_t base_word_idx;
uint32_t blk_max;
const struct mpc_sie_memory_range_t* limit_range;
uint32_t limit_block_idx;
uint32_t limit_word_idx;
uint32_t mask;
uint32_t norm_base;
uint32_t norm_limit;
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
/*
* Check that the addresses are within the controlled regions
* of this MPC
*/
if(!is_ctrl_by_range_list(dev, base, &base_range) ||
!is_ctrl_by_range_list(dev, limit, &limit_range)) {
return MPC_SIE_INTERN_ERR_NOT_IN_RANGE;
}
/* Base and limit should be part of the same range */
if(base_range != limit_range) {
return MPC_SIE_INTERN_ERR_INVALID_RANGE;
}
*range = base_range;
block_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET));
/* Base and limit+1 addresses must be aligned on the MPC block size */
if(base % block_size || (limit+1) % block_size) {
return MPC_SIE_INTERN_ERR_NOT_ALIGNED;
}
/*
* Get a normalized address that is an offset from the beginning
* of the lowest range controlled by the MPC
*/
norm_base = (base - base_range->base) + base_range->range_offset;
norm_limit = (limit - base_range->base) + base_range->range_offset;
/*
* Calculate block index and to which 32 bits word it belongs
*/
limit_block_idx = norm_limit/block_size;
limit_word_idx = limit_block_idx/32;
base_block_idx = norm_base/block_size;
base_word_idx = base_block_idx/32;
if(base_block_idx > limit_block_idx) {
return MPC_SIE_INTERN_ERR_INVALID_RANGE;
}
/* Transmit the information to the caller */
*nr_words = limit_word_idx - base_word_idx + 1;
*first_word_idx = base_word_idx;
/* Limit to the highest block that can be configured */
blk_max = p_mpc->blk_max;
if((limit_word_idx > blk_max) || (base_word_idx > blk_max)) {
return MPC_SIE_INTERN_ERR_BLK_IDX_TOO_HIGH;
}
/*
* Create the mask for the first word to only select the limit N bits
*/
*first_word_mask = ~((1 << (base_block_idx % 32)) - 1);
/*
* Create the mask for the limit word to select only the first M bits.
*/
*limit_word_mask = (1 << ((limit_block_idx+1) % 32)) - 1;
/*
* If limit_word_mask is 0, it means that the limit touched block index is
* the limit in its word, so the limit word mask has all its bits selected
*/
if(*limit_word_mask == 0) {
*limit_word_mask = 0xFFFFFFFF;
}
/*
* If the blocks to configure are all packed in one word, only
* touch this word.
* Code using the computed masks should test if this mask
* is non-zero, and if so, only use this one instead of the limit_word_mask
* and first_word_mask.
* As the only bits that are the same in both masks are the 1 that we want
* to select, just use XOR to extract them.
*/
if(base_word_idx == limit_word_idx) {
mask = ~(*first_word_mask ^ *limit_word_mask);
*first_word_mask = mask;
*limit_word_mask = mask;
}
return MPC_SIE_INTERN_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev,
const struct mpc_sie_memory_range_t** range_list,
uint8_t nbr_of_ranges)
{
if((range_list == NULL) || (nbr_of_ranges == 0)) {
return MPC_SIE_INVALID_ARG;
}
dev->data->sie_version = get_sie_version(dev);
if ((dev->data->sie_version != SIE200) &&
(dev->data->sie_version != SIE300)) {
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
}
dev->data->range_list = range_list;
dev->data->nbr_of_ranges = nbr_of_ranges;
dev->data->is_initialized = true;
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev,
uint32_t* blk_size)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if(blk_size == 0) {
return MPC_SIE_INVALID_ARG;
}
/* Calculate the block size in byte according to the manual */
*blk_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET));
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev,
const uint32_t base,
const uint32_t limit,
enum mpc_sie_sec_attr_t attr)
{
enum mpc_sie_intern_error_t error;
uint32_t first_word_idx;
uint32_t first_word_mask;
uint32_t i;
uint32_t limit_word_mask;
uint32_t limit_word_idx;
uint32_t nr_words;
const struct mpc_sie_memory_range_t* range;
uint32_t word_value;
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
/* Get the bitmasks used to select the bits in the LUT */
error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words,
&first_word_mask, &limit_word_mask);
limit_word_idx = first_word_idx + nr_words - 1;
if(error != MPC_SIE_INTERN_ERR_NONE) {
/* Map internal error code lower than 0 to a generic errpr */
if(error < 0) {
return MPC_SIE_ERR_INVALID_RANGE;
}
return (enum mpc_sie_error_t)error;
}
/*
* The memory range should allow accesses in with the wanted security
* attribute if it requires special attribute for successful accesses
*/
if(range->attr != attr) {
return MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE;
}
/*
* Starts changing actual configuration so issue DMB to ensure every
* transaction has completed by now
*/
__DMB();
/* Set the block index to the first word that will be updated */
p_mpc->blk_idx = first_word_idx;
/* If only one word needs to be touched in the LUT */
if(nr_words == 1) {
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE_SEC_ATTR_NONSECURE) {
word_value |= first_word_mask;
} else {
word_value &= ~first_word_mask;
}
/*
* Set the index again because full word read or write could have
* incremented it
*/
p_mpc->blk_idx = first_word_idx;
p_mpc->blk_lutn = word_value;
/* Commit the configuration change */
__DSB();
__ISB();
return MPC_SIE_ERR_NONE;
}
/* First word */
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE_SEC_ATTR_NONSECURE) {
word_value |= first_word_mask;
} else {
word_value &= ~first_word_mask;
}
/*
* Set the index again because full word read or write could have
* incremented it
*/
p_mpc->blk_idx = first_word_idx;
/* Partially configure the first word */
p_mpc->blk_lutn = word_value;
/* Fully configure the intermediate words if there are any */
for(i=first_word_idx+1; i<limit_word_idx; i++) {
p_mpc->blk_idx = i;
if(attr == MPC_SIE_SEC_ATTR_NONSECURE) {
p_mpc->blk_lutn = 0xFFFFFFFF;
} else {
p_mpc->blk_lutn = 0x00000000;
}
}
/* Partially configure the limit word */
p_mpc->blk_idx = limit_word_idx;
word_value = p_mpc->blk_lutn;
if(attr == MPC_SIE_SEC_ATTR_NONSECURE) {
word_value |= limit_word_mask;
} else {
word_value &= ~limit_word_mask;
}
p_mpc->blk_idx = limit_word_idx;
p_mpc->blk_lutn = word_value;
/* Commit the configuration change */
__DSB();
__ISB();
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_get_region_config(
struct mpc_sie_dev_t* dev,
uint32_t base, uint32_t limit,
enum mpc_sie_sec_attr_t* attr)
{
enum mpc_sie_sec_attr_t attr_prev;
uint32_t block_size;
uint32_t block_size_mask;
enum mpc_sie_intern_error_t error;
uint32_t first_word_idx;
uint32_t first_word_mask;
uint32_t i;
uint32_t limit_word_idx;
uint32_t limit_word_mask;
uint32_t nr_words;
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
const struct mpc_sie_memory_range_t* range;
uint32_t word_value;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if(attr == 0) {
return MPC_SIE_INVALID_ARG;
}
/*
* Initialize the security attribute to mixed in case of early
* termination of this function. A caller that does not check the
* returned error will act as if it does not know anything about the
* region queried, which is the safest bet
*/
*attr = MPC_SIE_SEC_ATTR_MIXED;
/*
* If the base and limit are not aligned, align them and make sure
* that the resulting region fully includes the original region
*/
block_size = (1 << (p_mpc->blk_cfg + MPC_SIE_BLK_CFG_OFFSET));
block_size_mask = block_size - 1;
base &= ~(block_size_mask);
limit &= ~(block_size_mask);
limit += block_size - 1; /* Round to the upper block address,
* and then remove one to get the preceding
* address.
*/
/* Get the bitmasks used to select the bits in the LUT */
error = get_lut_masks(dev, base, limit, &range, &first_word_idx, &nr_words,
&first_word_mask, &limit_word_mask);
limit_word_idx = first_word_idx+nr_words - 1;
if(error != MPC_SIE_INTERN_ERR_NONE) {
/* Map internal error code lower than 0 to generic error */
if(error < 0) {
return MPC_SIE_ERR_INVALID_RANGE;
}
return (enum mpc_sie_error_t)error;
}
/* Set the block index to the first word that will be updated */
p_mpc->blk_idx = first_word_idx;
/* If only one word needs to be touched in the LUT */
if(nr_words == 1) {
word_value = p_mpc->blk_lutn;
word_value &= first_word_mask;
if(word_value == 0) {
*attr = MPC_SIE_SEC_ATTR_SECURE;
/*
* If there are differences between the mask and the word value,
* it means that the security attributes of blocks are mixed
*/
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE_SEC_ATTR_MIXED;
} else {
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
}
return MPC_SIE_ERR_NONE;
}
/* Get the partial configuration of the first word */
word_value = p_mpc->blk_lutn & first_word_mask;
if(word_value == 0x00000000) {
*attr = MPC_SIE_SEC_ATTR_SECURE;
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE_SEC_ATTR_MIXED;
/*
* Bail out as the security attribute will be the same regardless
* of the configuration of other blocks
*/
return MPC_SIE_ERR_NONE;
} else {
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
}
/*
* Store the current found attribute, to check that all the blocks indeed
* have the same security attribute.
*/
attr_prev = *attr;
/* Get the configuration of the intermediate words if there are any */
for(i=first_word_idx+1; i<limit_word_idx; i++) {
p_mpc->blk_idx = i;
word_value = p_mpc->blk_lutn;
if(word_value == 0x00000000) {
*attr = MPC_SIE_SEC_ATTR_SECURE;
} else if(word_value == 0xFFFFFFFF) {
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
} else {
*attr = MPC_SIE_SEC_ATTR_MIXED;
return MPC_SIE_ERR_NONE;
}
/* If the attribute is different than the one found before, bail out */
if(*attr != attr_prev) {
*attr = MPC_SIE_SEC_ATTR_MIXED;
return MPC_SIE_ERR_NONE;
}
attr_prev = *attr;
}
/* Get the partial configuration of the limit word */
p_mpc->blk_idx = limit_word_idx;
word_value = p_mpc->blk_lutn & limit_word_mask;
if(word_value == 0x00000000) {
*attr = MPC_SIE_SEC_ATTR_SECURE;
} else if(word_value ^ first_word_mask) {
*attr = MPC_SIE_SEC_ATTR_MIXED;
return MPC_SIE_ERR_NONE;
} else {
*attr = MPC_SIE_SEC_ATTR_NONSECURE;
}
if(*attr != attr_prev) {
*attr = MPC_SIE_SEC_ATTR_MIXED;
return MPC_SIE_ERR_NONE;
}
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev,
uint32_t* ctrl_val)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if(ctrl_val == 0) {
return MPC_SIE_INVALID_ARG;
}
*ctrl_val = p_mpc->ctrl;
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev,
uint32_t mpc_ctrl)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
p_mpc->ctrl = mpc_ctrl;
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev,
enum mpc_sie_sec_resp_t* sec_rep)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
bool gating_present = false;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if(sec_rep == NULL) {
return MPC_SIE_INVALID_ARG;
}
if (dev->data->sie_version == SIE200) {
if(p_mpc->ctrl & MPC_SIE200_CTRL_SEC_RESP) {
*sec_rep = MPC_SIE_RESP_BUS_ERROR;
} else {
*sec_rep = MPC_SIE_RESP_RAZ_WI;
}
} else if (dev->data->sie_version == SIE300) {
mpc_sie_is_gating_present(dev, &gating_present);
if (!gating_present) {
return MPC_SIE_ERR_GATING_NOT_PRESENT;
}
if(p_mpc->ctrl & MPC_SIE300_CTRL_SEC_RESP) {
/* MPC returns a BUS ERROR response */
*sec_rep = MPC_SIE_RESP_BUS_ERROR;
} else {
/* MPC sets the ready signals LOW, which stalls any transactions */
*sec_rep = MPC_SIE_RESP_WAIT_GATING_DISABLED;
}
} else {
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
}
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev,
enum mpc_sie_sec_resp_t sec_rep)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
bool gating_present = false;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if (dev->data->sie_version == SIE200) {
if (sec_rep == MPC_SIE_RESP_BUS_ERROR) {
p_mpc->ctrl |= MPC_SIE200_CTRL_SEC_RESP;
} else if (sec_rep == MPC_SIE_RESP_RAZ_WI) {
p_mpc->ctrl &= ~MPC_SIE200_CTRL_SEC_RESP;
} else {
return MPC_SIE_INVALID_ARG;
}
} else if (dev->data->sie_version == SIE300) {
mpc_sie_is_gating_present(dev, &gating_present);
if (!gating_present) {
return MPC_SIE_ERR_GATING_NOT_PRESENT;
}
if (sec_rep == MPC_SIE_RESP_BUS_ERROR) {
p_mpc->ctrl |= MPC_SIE300_CTRL_SEC_RESP;
} else if (sec_rep == MPC_SIE_RESP_WAIT_GATING_DISABLED) {
p_mpc->ctrl &= ~MPC_SIE300_CTRL_SEC_RESP;
} else {
return MPC_SIE_INVALID_ARG;
}
} else {
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
}
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
p_mpc->int_en |= MPC_SIE_INT_BIT;
return MPC_SIE_ERR_NONE;
}
void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
p_mpc->int_en &= ~MPC_SIE_INT_BIT;
}
void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
p_mpc->int_clear = MPC_SIE_INT_BIT;
}
uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
return (p_mpc->int_stat & MPC_SIE_INT_BIT);
}
enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
p_mpc->ctrl |= (MPC_SIE_CTRL_AUTOINCREMENT
| MPC_SIE_CTRL_SEC_LOCK_DOWN);
return MPC_SIE_ERR_NONE;
}
enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev,
bool* gating_present)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
if(dev->data->is_initialized != true) {
return MPC_SIE_NOT_INIT;
}
if (dev->data->sie_version != SIE300) {
return MPC_SIE_UNSUPPORTED_HARDWARE_VERSION;
}
*gating_present = (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_PRESENT);
return MPC_SIE_ERR_NONE;
}
uint32_t get_sie_version(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
return p_mpc->pidr0 & MPC_PIDR0_SIE_VERSION_MASK;
}
bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
return (bool)(p_mpc->ctrl & MPC_SIE300_CTRL_GATE_ACK);
}
void mpc_sie_request_gating(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
p_mpc->ctrl |= MPC_SIE300_CTRL_GATE_REQ;
}
void mpc_sie_release_gating(struct mpc_sie_dev_t* dev)
{
struct mpc_sie_reg_map_t* p_mpc =
(struct mpc_sie_reg_map_t*)dev->cfg->base;
p_mpc->ctrl &= ~MPC_SIE300_CTRL_GATE_REQ;
}

View File

@ -1,354 +0,0 @@
/*
* Copyright (c) 2016-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file mpc_sie_drv.h
* \brief Generic driver for ARM SIE Memory Protection
* Controllers (MPC).
*/
#ifndef __MPC_SIE__DRV_H__
#define __MPC_SIE__DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Error code returned by the driver functions */
enum mpc_sie_error_t {
MPC_SIE_ERR_NONE, /*!< No error */
MPC_SIE_INVALID_ARG, /*!< MPC invalid input arguments */
MPC_SIE_NOT_INIT, /*!< MPC not initialized */
MPC_SIE_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range
* controlled by the MPC */
MPC_SIE_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size
* of this MPC
*/
MPC_SIE_ERR_INVALID_RANGE, /*!< The given address range to configure
* is invalid. This could be because:
* - The base and limit swapped
* - The base and limit addresses
* are in different ranges
*/
MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be
* accessed with the wanted
* security attributes
*/
MPC_SIE_UNSUPPORTED_HARDWARE_VERSION, /*!< MPC hardware version read from
* PIDR0 is not supported
*/
MPC_SIE_ERR_GATING_NOT_PRESENT /*!< MPC gating not present in HW */
};
/* Security attribute used in various place of the API */
enum mpc_sie_sec_attr_t {
MPC_SIE_SEC_ATTR_SECURE, /*!< Secure attribute */
MPC_SIE_SEC_ATTR_NONSECURE, /*!< Non-secure attribute */
/*!< Used when getting the configuration of a memory range and some blocks
* are secure whereas some other are non secure
*/
MPC_SIE_SEC_ATTR_MIXED,
};
/* What can happen when trying to do an illegal memory access */
enum mpc_sie_sec_resp_t {
MPC_SIE_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */
MPC_SIE_RESP_BUS_ERROR, /*!< Bus error */
MPC_SIE_RESP_WAIT_GATING_DISABLED /*!< Wait until gating is disabled */
};
/* Description of a memory range controlled by the MPC */
struct mpc_sie_memory_range_t {
const uint32_t base; /*!< Base address (included in the range) */
const uint32_t limit; /*!< Limit address (included in the range) */
const uint32_t range_offset; /*!< Offset of current range area to the 0
* point of the whole area (the sum of the
* sizes of the previous memory ranges
* covered by the same MPC)
*/
const enum mpc_sie_sec_attr_t attr; /*!< Optional security attribute
* needed to be matched when
* accessing this range.
* For example, the non-secure
* alias of a memory region can not
* be accessed using secure access,
* and configuring the MPC to
* secure using that range will not
* be permitted by the driver.
*/
};
/* ARM MPC SIE device configuration structure */
struct mpc_sie_dev_cfg_t {
const uint32_t base; /*!< MPC base address */
};
/* ARM MPC SIE device data structure */
struct mpc_sie_dev_data_t {
/*!< Array of pointers to memory ranges controlled by the MPC */
const struct mpc_sie_memory_range_t** range_list;
uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */
bool is_initialized; /*!< Indicates if the MPC driver
* is initialized and enabled
*/
uint32_t sie_version; /*!< SIE version */
};
/* ARM MPC SIE device structure */
struct mpc_sie_dev_t {
const struct mpc_sie_dev_cfg_t* const cfg; /*!< MPC configuration */
struct mpc_sie_dev_data_t* const data; /*!< MPC data */
};
/**
* \brief Initializes a MPC device.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[in] range_list List of memory ranges controller by the MPC
* (\ref mpc_sie_memory_range_t). This list can not
* freed after the initializations.
* \param[in] nbr_of_ranges Number of memory ranges
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev,
const struct mpc_sie_memory_range_t** range_list,
uint8_t nbr_of_ranges);
/**
* \brief Gets MPC block size. All regions must be aligned on this block
* size (base address and limit+1 address).
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[out] blk_size MPC block size
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev,
uint32_t* blk_size);
/**
* \brief Configures a memory region (base and limit included).
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[in] base Base address of the region to poll. This bound is
* included. It does not need to be aligned in any way.
*
* \param[in] limit Limit address of the region to poll. This bound is
* included. (limit+1) does not need to be aligned
* in any way.
* \param[in] attr Security attribute of the region. If the region has mixed
* secure/non-secure, a special value is returned
* (\ref mpc_sie_sec_attr_t).
*
* In case base and limit+1 addresses are not aligned on
* the block size, the enclosing region with base and
* limit+1 aligned on block size will be queried.
* In case of early termination of the function (error), the
* security attribute will be set to MPC_SIE_ATTR_MIXED.
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev,
const uint32_t base,
const uint32_t limit,
enum mpc_sie_sec_attr_t attr);
/**
* \brief Gets a memory region configuration(base and limit included).
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[in] base Base address of the region to get the configuration.
* \param[in] limit Limit address of the region to get the configuration.
* \param[out] attr Security attribute of the region
* \ref mpc_sie_sec_attr_t
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_get_region_config(struct mpc_sie_dev_t* dev,
uint32_t base,
uint32_t limit,
enum mpc_sie_sec_attr_t* attr);
/**
* \brief Gets the MPC control value.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[out] ctrl_val Current MPC control value.
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev,
uint32_t* ctrl_val);
/**
* \brief Sets the MPC control value.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[in] mpc_ctrl New MPC control value
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev,
uint32_t mpc_ctrl);
/**
* \brief Gets the configured secure response.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[out] sec_rep Configured secure response (\ref mpc_sie_sec_resp_t).
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev,
enum mpc_sie_sec_resp_t* sec_rep);
/**
* \brief Sets the response type when SW asks to gate the incoming transfers.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[in] sec_rep Secure response to configure (\ref mpc_sie_sec_resp_t).
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev,
enum mpc_sie_sec_resp_t sec_rep);
/**
* \brief Enables MPC interrupt.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev);
/**
* \brief Disables MPC interrupt
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev);
/**
* \brief Clears MPC interrupt.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev);
/**
* \brief Returns the MPC interrupt state.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \return Returns 1 if the interrupt is active, 0 otherwise.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev);
/**
* \brief Locks down the MPC configuration.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev);
/**
* \brief Returns if gating is present in hardware.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
* \param[out] gating_present Returns if gating is present in hardware.
*
* \return Returns error code as specified in \ref mpc_sie_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev,
bool* gating_present);
/**
* \brief Returns the value of Peripheral ID 0 register.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \return Returns the value of Peripheral ID 0 register.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t get_sie_version(struct mpc_sie_dev_t* dev);
/**
* \brief Reads bit indicating acknowledge for gating incoming transfers.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \return True if acknowledge is set.
*
* \note This function doesn't check if dev is NULL.
*/
bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev);
/**
* \brief Sets bit to request for gating incoming transfers.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie_request_gating(struct mpc_sie_dev_t* dev);
/**
* \brief Clears bit to request for gating incoming transfers.
*
* \param[in] dev MPC device \ref mpc_sie_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void mpc_sie_release_gating(struct mpc_sie_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __MPC_SIE_DRV_H__ */

View File

@ -1,152 +0,0 @@
/*
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "mpu_armv8m_drv.h"
#include "cmsis.h"
/*
* FixMe:
* This is a beta quality driver for MPU in v8M. To be finalized.
*/
enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
uint32_t privdef_en,
uint32_t hfnmi_en)
{
/*No error checking*/
MPU_Type *mpu = (MPU_Type *)dev->base;
/*
* FixMe: Set 3 pre-defined MAIR_ATTR for memory. The attributes come
* from default memory map, need to check if fine-tune is necessary.
*
* MAIR0_0: Peripheral, Device-nGnRE.
* MAIR0_1: Code, WT RA. Same attr for Outer and Inner.
* MAIR0_2: SRAM, WBWA RA. Same attr for Outer and Inner.
*/
mpu->MAIR0 = (MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL << MPU_MAIR0_Attr0_Pos) |
(MPU_ARMV8M_MAIR_ATTR_CODE_VAL << MPU_MAIR0_Attr1_Pos) |
(MPU_ARMV8M_MAIR_ATTR_DATA_VAL << MPU_MAIR0_Attr2_Pos);
mpu->CTRL =
(privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
(hfnmi_en ? MPU_CTRL_HFNMIENA_Msk : 0);
/*Ensure all configuration is written before enable*/
mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
/* Enable MPU before next instruction */
__DSB();
__ISB();
return MPU_ARMV8M_OK;
}
enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
/* Reset all fields as enable does full setup */
mpu->CTRL = 0;
return MPU_ARMV8M_OK;
}
enum mpu_armv8m_error_t mpu_armv8m_region_enable(
struct mpu_armv8m_dev_t *dev,
struct mpu_armv8m_region_cfg_t *region_cfg)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
uint32_t ctrl_before;
uint32_t base_cfg;
uint32_t limit_cfg;
/*FIXME : Add complete error checking*/
if ((region_cfg->region_base & ~MPU_RBAR_BASE_Msk) != 0) {
return MPU_ARMV8M_ERROR;
}
/* region_limit doesn't need to be aligned but the scatter
* file needs to be setup to ensure that partitions do not overlap.
*/
ctrl_before = mpu->CTRL;
mpu->CTRL = 0;
mpu->RNR = region_cfg->region_nr & MPU_RNR_REGION_Msk;
/* This 0s the lower bits of the base address */
base_cfg = region_cfg->region_base & MPU_RBAR_BASE_Msk;
base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
mpu->RBAR = base_cfg;
/*This 0s the lower bits of base address but they are treated as 1 */
limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
limit_cfg |= (region_cfg->region_attridx << MPU_RLAR_AttrIndx_Pos) &
MPU_RLAR_AttrIndx_Msk;
limit_cfg |= MPU_RLAR_EN_Msk;
mpu->RLAR = limit_cfg;
/*Restore main MPU control*/
mpu->CTRL = ctrl_before;
/* Enable MPU before the next instruction */
__DSB();
__ISB();
return ret_val;
}
enum mpu_armv8m_error_t mpu_armv8m_region_disable(
struct mpu_armv8m_dev_t *dev,
uint32_t region_nr)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
uint32_t ctrl_before;
/*FIXME : Add complete error checking*/
ctrl_before = mpu->CTRL;
mpu->CTRL = 0;
mpu->RNR = region_nr & MPU_RNR_REGION_Msk;
mpu->RBAR = 0;
mpu->RLAR = 0;
/*Restore main MPU control*/
mpu->CTRL = ctrl_before;
return ret_val;
}
enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
{
MPU_Type *mpu = (MPU_Type *)dev->base;
uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
while (i > 0) {
mpu_armv8m_region_disable(dev, i-1);
i--;
}
return MPU_ARMV8M_OK;
}

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __MPU_ARMV8M_DRV_H__
#define __MPU_ARMV8M_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PRIVILEGED_DEFAULT_ENABLE 1
#define HARDFAULT_NMI_ENABLE 1
/* MAIR_ATTR */
#define MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL 0x04
#define MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX 0
#define MPU_ARMV8M_MAIR_ATTR_CODE_VAL 0xAA
#define MPU_ARMV8M_MAIR_ATTR_CODE_IDX 1
#define MPU_ARMV8M_MAIR_ATTR_DATA_VAL 0xFF
#define MPU_ARMV8M_MAIR_ATTR_DATA_IDX 2
struct mpu_armv8m_dev_t {
const uint32_t base;
};
enum mpu_armv8m_error_t {
MPU_ARMV8M_OK,
MPU_ARMV8M_ERROR
};
enum mpu_armv8m_attr_exec_t {
MPU_ARMV8M_XN_EXEC_OK,
MPU_ARMV8M_XN_EXEC_NEVER
};
enum mpu_armv8m_attr_access_t {
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
MPU_ARMV8M_AP_RO_PRIV_ONLY,
MPU_ARMV8M_AP_RO_PRIV_UNPRIV
};
enum mpu_armv8m_attr_shared_t {
MPU_ARMV8M_SH_NONE,
MPU_ARMV8M_SH_UNUSED,
MPU_ARMV8M_SH_OUTER,
MPU_ARMV8M_SH_INNER
};
struct mpu_armv8m_region_cfg_t {
uint32_t region_nr;
uint32_t region_base;
uint32_t region_limit;
uint32_t region_attridx;
enum mpu_armv8m_attr_exec_t attr_exec;
enum mpu_armv8m_attr_access_t attr_access;
enum mpu_armv8m_attr_shared_t attr_sh;
};
struct mpu_armv8m_region_cfg_raw_t {
uint32_t region_nr;
uint32_t region_base;
uint32_t region_limit;
};
/**
* \brief Enable MPU
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] privdef_en privilege default region 1:enable 0:disable
* \param[in] hfnmi_en mpu for hard fault & nmi 1:enable 0:disable
*
* \return Error code \ref mpu_armv8m_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
uint32_t privdef_en,
uint32_t hfnmi_en);
/**
* \brief Disable MPU
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
/**
* \brief Disable MPU and clean all regions
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
/**
* \brief Enable MPU Region
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] region_cfg MPU region config \ref mpu_armv8m_region_cfg_t
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_region_enable(
struct mpu_armv8m_dev_t *dev,
struct mpu_armv8m_region_cfg_t *region_cfg);
/**
* \brief Disable MPU Region
*
* \param[in] dev MPU device \ref mpu_armv8m_dev_t
* \param[in] region_nr Region number
*
* \return Error code \ref arm_mpu_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum mpu_armv8m_error_t mpu_armv8m_region_disable(
struct mpu_armv8m_dev_t *dev,
uint32_t region_nr);
#ifdef __cplusplus
}
#endif
#endif /* __MPU_ARMV8M_DRV_H__ */

View File

@ -1,347 +0,0 @@
/*
* Copyright (c) 2017-2019 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ppc_sse200_drv.h"
/* SPCTRL PPCs control memory mapped registers access structure */
struct arm_spctrl_ppc_sse200_t {
volatile uint32_t reserved[8];
volatile uint32_t secppcintstat; /* Secure PPC Interrupt Status */
volatile uint32_t secppcintclr; /* Secure PPC Interrupt Clear */
volatile uint32_t secppcinten; /* Secure PPC Interrupt Enable */
volatile uint32_t reserved1[9];
volatile uint32_t ahbnsppc0; /* Non-Secure Access AHB slave Peripheral
* Protection Control #0
*/
volatile uint32_t reserved2[3]; /* Reserved for Future Non-secure Access
* AHB Slave Peripheral Protection Control
*/
volatile uint32_t ahbnsppcexp0; /* Expansion 0 Non_Secure Access AHB
* slave Peripheral Protection Control
*/
volatile uint32_t ahbnsppcexp1; /* Expansion 1 Non_Secure Access AHB
* slave Peripheral Protection Control
*/
volatile uint32_t ahbnsppcexp2; /* Expansion 2 Non_Secure Access AHB
* slave Peripheral Protection Control
*/
volatile uint32_t ahbnsppcexp3; /* Expansion 3 Non_Secure Access AHB
* slave Peripheral Protection Control
*/
volatile uint32_t apbnsppc0; /* Non-Secure Access APB slave Peripheral
* Protection Control 0
*/
volatile uint32_t apbnsppc1; /* Non-Secure Access APB slave Peripheral
* Protection Control 1
*/
volatile uint32_t reserved3[2]; /* Non-Secure Access APB slave Peripheral
* Protection Control [3:1]
*/
volatile uint32_t apbnsppcexp0; /* Expansion 0 Non_Secure Access APB
* slave Peripheral Protection Control
*/
volatile uint32_t apbnsppcexp1; /* Expansion 1 Non_Secure Access APB
* slave Peripheral Protection Control
*/
volatile uint32_t apbnsppcexp2; /* Expansion 2 Non_Secure Access APB
* slave Peripheral Protection Control
*/
volatile uint32_t apbnsppcexp3; /* Expansion 3 Non_Secure Access APB
* slave Peripheral Protection Control
*/
volatile uint32_t ahbspppc0; /* Secure Unprivileged Access AHB slave
* Peripheral Protection Control 0
*/
volatile uint32_t reserved4[3]; /* Reserved for Future Secure Unprivileged
* Access AHB slave Peripheral Protection
* Control
*/
volatile uint32_t ahbspppcexp0; /* Expansion 0 Secure Unprivileged Access
* AHB slave Peripheral Protection Control
*/
volatile uint32_t ahbspppcexp1; /* Expansion 1 Secure Unprivileged Access
* AHB slave Peripheral Protection Control
*/
volatile uint32_t ahbspppcexp2; /* Expansion 2 Secure Unprivileged Access
* AHB slave Peripheral Protection Control
*/
volatile uint32_t ahbspppcexp3; /* Expansion 3 Secure Unprivileged Access
* AHB slave Peripheral Protection Control
*/
volatile uint32_t apbspppc0; /* Secure Unprivileged Access APB slave
* Peripheral 0
*/
volatile uint32_t apbspppc1; /* Secure Unprivileged Access APB slave
* Peripheral 1
*/
volatile uint32_t reserved5[2]; /* Reserved for Future Secure Unprivileged
* Access APB slave Peripheral Protection
* Control
*/
volatile uint32_t apbspppcexp0; /* Expansion 0 Secure Unprivileged Access
* APB slave Peripheral Protection
* Control
*/
volatile uint32_t apbspppcexp1; /* Expansion 1 Secure Unprivileged Access
* APB slave Peripheral Protection
* Control
*/
volatile uint32_t apbspppcexp2; /* Expansion 2 Secure Unprivileged Access
* APB slave Peripheral Protection
* Control
*/
volatile uint32_t apbspppcexp3; /* Expansion 3 Secure Unprivileged Access
* APB slave Peripheral Protection
* Control
*/
};
/* NSPCTRL PPCs memory mapped register access structure */
struct arm_nspctrl_ppc_sse200_t {
volatile uint32_t reserved[36];
volatile uint32_t ahbnspppc0;
volatile uint32_t reserved1[3];
volatile uint32_t ahbnspppcexp0;
volatile uint32_t ahbnspppcexp1;
volatile uint32_t ahbnspppcexp2;
volatile uint32_t ahbnspppcexp3;
volatile uint32_t apbnspppc0;
volatile uint32_t apbnspppc1;
volatile uint32_t reserved2[2];
volatile uint32_t apbnspppcexp0;
volatile uint32_t apbnspppcexp1;
volatile uint32_t apbnspppcexp2;
volatile uint32_t apbnspppcexp3;
};
/* PPC interrupt position mask */
#define APB_PPC0_INT_POS_MASK (1UL << 0)
#define APB_PPC1_INT_POS_MASK (1UL << 1)
/* Reserved bits 2:3 */
#define APB_PPCEXP0_INT_POS_MASK (1UL << 4)
#define APB_PPCEXP1_INT_POS_MASK (1UL << 5)
#define APB_PPCEXP2_INT_POS_MASK (1UL << 6)
#define APB_PPCEXP3_INT_POS_MASK (1UL << 7)
/* Reserved bits 8:15 */
#define AHB_PPC0_INT_POS_MASK (1UL << 16)
/* Reserved bits 17:19 */
#define AHB_PPCEXP0_INT_POS_MASK (1UL << 20)
#define AHB_PPCEXP1_INT_POS_MASK (1UL << 21)
#define AHB_PPCEXP2_INT_POS_MASK (1UL << 22)
#define AHB_PPCEXP3_INT_POS_MASK (1UL << 23)
/* Reserved bits 24:31 */
/* ARM PPC state definitions */
#define PPC_SSE200_INITIALIZED (1 << 0)
/* Default peripheral states */
#define SECURE_AS_DEFAULT_PERIPHERAL_STATE 1
#define PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE 1
void ppc_sse200_init(struct ppc_sse200_dev_t* dev,
enum ppc_sse200_name_t ppc_name)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
struct arm_nspctrl_ppc_sse200_t* p_nspctrl =
(struct arm_nspctrl_ppc_sse200_t*)dev->cfg->nspctrl_base;
switch(ppc_name) {
case AHB_PPC0:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppc0;
dev->data->p_sp_ppc = &p_spctrl->ahbspppc0;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppc0;
dev->data->int_bit_mask = AHB_PPC0_INT_POS_MASK;
break;
case AHB_PPC_EXP0:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp0;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp0;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp0;
dev->data->int_bit_mask = AHB_PPCEXP0_INT_POS_MASK;
break;
case AHB_PPC_EXP1:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp1;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp1;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp1;
dev->data->int_bit_mask = AHB_PPCEXP1_INT_POS_MASK;
break;
case AHB_PPC_EXP2:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp2;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp2;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp2;
dev->data->int_bit_mask = AHB_PPCEXP2_INT_POS_MASK;
break;
case AHB_PPC_EXP3:
dev->data->p_ns_ppc = &p_spctrl->ahbnsppcexp3;
dev->data->p_sp_ppc = &p_spctrl->ahbspppcexp3;
dev->data->p_nsp_ppc = &p_nspctrl->ahbnspppcexp3;
dev->data->int_bit_mask = AHB_PPCEXP3_INT_POS_MASK;
break;
case APB_PPC0:
dev->data->p_ns_ppc = &p_spctrl->apbnsppc0;
dev->data->p_sp_ppc = &p_spctrl->apbspppc0;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc0;
dev->data->int_bit_mask = APB_PPC0_INT_POS_MASK;
break;
case APB_PPC1:
dev->data->p_ns_ppc = &p_spctrl->apbnsppc1;
dev->data->p_sp_ppc = &p_spctrl->apbspppc1;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppc1;
dev->data->int_bit_mask = APB_PPC1_INT_POS_MASK;
break;
case APB_PPC_EXP0:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp0;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp0;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp0;
dev->data->int_bit_mask = APB_PPCEXP0_INT_POS_MASK;
break;
case APB_PPC_EXP1:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp1;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp1;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp1;
dev->data->int_bit_mask = APB_PPCEXP1_INT_POS_MASK;
break;
case APB_PPC_EXP2:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp2;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp2;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp2;
dev->data->int_bit_mask = APB_PPCEXP2_INT_POS_MASK;
break;
case APB_PPC_EXP3:
dev->data->p_ns_ppc = &p_spctrl->apbnsppcexp3;
dev->data->p_sp_ppc = &p_spctrl->apbspppcexp3;
dev->data->p_nsp_ppc = &p_nspctrl->apbnspppcexp3;
dev->data->int_bit_mask = APB_PPCEXP3_INT_POS_MASK;
break;
/* default: The default is not defined intentionally to force the
* compiler to check that all enumeration values are
* covered in the switch.
*/
}
dev->data->state = PPC_SSE200_INITIALIZED;
}
enum ppc_sse200_error_t ppc_sse200_config_peripheral(
struct ppc_sse200_dev_t* dev,
uint8_t periph,
enum ppc_sse200_sec_attr_t sec_attr,
enum ppc_sse200_priv_attr_t priv_attr)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PPC_SSE200_NOT_INIT;
}
if(sec_attr == PPC_SSE200_SECURE_ONLY) {
/* Sets secure attribute */
*(dev->data->p_ns_ppc) &= ~(1U << periph);
/* Uses secure unprivileged access address (SPCTRL) to set privilege
* attribute
*/
if(priv_attr == PPC_SSE200_PRIV_ONLY) {
*(dev->data->p_sp_ppc) &= ~(1U << periph);
} else {
*(dev->data->p_sp_ppc) |= (1U << periph);
}
} else {
/* Sets secure attribute */
*(dev->data->p_ns_ppc) |= (1U << periph);
/* Uses non-secure unprivileged access address (NSPCTRL) to set
* privilege attribute
*/
if(priv_attr == PPC_SSE200_PRIV_ONLY) {
*(dev->data->p_nsp_ppc) &= ~(1U << periph);
} else {
*(dev->data->p_nsp_ppc) |= (1U << periph);
}
}
return PPC_SSE200_ERR_NONE;
}
uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev,
uint8_t periph)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return SECURE_AS_DEFAULT_PERIPHERAL_STATE;
}
return ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0);
}
uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev,
uint8_t periph)
{
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE;
}
if ((*(dev->data->p_ns_ppc) & (1U << periph)) == 0) {
/* Returns secure unprivileged access address (SPCTRL) */
return ((*(dev->data->p_sp_ppc) & (1U << periph)) == 0);
} else {
/* Returns non-secure unprivileged access address (NSPCTRL) */
return ((*(dev->data->p_nsp_ppc) & (1U << periph)) == 0);
}
}
enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return PPC_SSE200_NOT_INIT;
}
p_spctrl->secppcinten |= dev->data->int_bit_mask;
return PPC_SSE200_ERR_NONE;
}
void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state == PPC_SSE200_INITIALIZED) {
p_spctrl->secppcinten &= ~(dev->data->int_bit_mask);
}
}
void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state == PPC_SSE200_INITIALIZED) {
p_spctrl->secppcintclr = dev->data->int_bit_mask;
}
}
uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev)
{
struct arm_spctrl_ppc_sse200_t* p_spctrl =
(struct arm_spctrl_ppc_sse200_t*)dev->cfg->spctrl_base;
if(dev->data->state != PPC_SSE200_INITIALIZED) {
return 0;
}
return ((p_spctrl->secppcintstat & dev->data->int_bit_mask) != 0);
}

View File

@ -1,201 +0,0 @@
/*
* Copyright (c) 2017-2019 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file ppc_sse200_drv.h
* \brief Generic driver for ARM SEE 200 Peripheral Protection
* Controllers (PPC).
*/
#ifndef __PPC_SSE_200_DRV_H__
#define __PPC_SSE_200_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Secure Privilege Control Block aka SPCTRL */
/* Non-Secure Privilege Control Block aka NSPCTRL */
/* ARM TrustZone PPC device configuration structure */
struct ppc_sse200_dev_cfg_t {
uint32_t const spctrl_base; /*!< SPCTRL base address */
uint32_t const nspctrl_base; /*!< NSPCTRL base address */
};
/* ARM TrustZone PPC device data structure */
struct ppc_sse200_dev_data_t {
volatile uint32_t* p_ns_ppc; /*!< Pointer to non-secure register */
volatile uint32_t* p_sp_ppc; /*!< Pointer to secure unprivileged
* register
*/
volatile uint32_t* p_nsp_ppc; /*!< Pointer to non-secure unprivileged
* register
*/
uint32_t int_bit_mask; /*!< Interrupt bit mask */
uint8_t state; /*!< Indicates if the PPC driver
* is initialized
*/
uint8_t reserved[3]; /*!< 32 bits alignment */
};
/* ARM PPC device structure */
struct ppc_sse200_dev_t {
const struct ppc_sse200_dev_cfg_t* const cfg; /*!< PPC configuration */
struct ppc_sse200_dev_data_t* const data; /*!< PPC data */
};
/* Security attribute used to configure the peripheral */
enum ppc_sse200_sec_attr_t {
PPC_SSE200_SECURE_ONLY, /*! Secure access */
PPC_SSE200_NONSECURE_ONLY, /*! Non-secure access */
};
/* Privilege attribute used to configure the peripheral */
enum ppc_sse200_priv_attr_t {
PPC_SSE200_PRIV_AND_NONPRIV, /*! Privilege and non-Privilege access */
PPC_SSE200_PRIV_ONLY, /*! Privilege only access */
};
/* ARM PPC error codes */
enum ppc_sse200_error_t {
PPC_SSE200_ERR_NONE = 0, /*!< No error */
PPC_SSE200_NOT_INIT, /*!< PPC not initialized */
};
/* ARM PPC names */
enum ppc_sse200_name_t {
AHB_PPC0 = 0, /*!< AHB PPC0 */
AHB_PPC_EXP0, /*!< Expansion 0 AHB PPC */
AHB_PPC_EXP1, /*!< Expansion 1 AHB PPC */
AHB_PPC_EXP2, /*!< Expansion 2 AHB PPC */
AHB_PPC_EXP3, /*!< Expansion 3 AHB PPC */
APB_PPC0, /*!< APB PPC0 */
APB_PPC1, /*!< APB PPC1 */
APB_PPC_EXP0, /*!< Expansion 0 APB PPC */
APB_PPC_EXP1, /*!< Expansion 1 APB PPC */
APB_PPC_EXP2, /*!< Expansion 2 APB PPC */
APB_PPC_EXP3 /*!< Expansion 3 APB PPC */
};
/**
* \brief Initialize the PPC device.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] ppc_name PPC name \ref ppc_sse200_name_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_init(struct ppc_sse200_dev_t* dev,
enum ppc_sse200_name_t ppc_name);
/**
* \brief Configures the PPC device.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
* \param[in] sec_attr Secure attribute value.
* \param[in] priv_attr Privilege attribute value.
*
* \return Returns error code as specified in \ref ppc_sse200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum ppc_sse200_error_t ppc_sse200_config_peripheral(
struct ppc_sse200_dev_t* dev,
uint8_t periph,
enum ppc_sse200_sec_attr_t sec_attr,
enum ppc_sse200_priv_attr_t priv_attr);
/**
* \brief Checks if the peripheral is configured as secure or non-secure.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
*
* \return Returns 1 for secure and 0 for non-secure.
* If the driver is not initialized the return value is 1 (secure) as
* it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_is_periph_secure(struct ppc_sse200_dev_t* dev,
uint8_t periph);
/**
* \brief Checks if the peripheral is configured as Privilege only or
* Privilege and non-Privilege access mode.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
* \param[in] periph Peripheral position in the PPC.
*
* \return Returns 1 for Privilege only configuration and 0 for Privilege and
* non-Privilege access.
* If the driver is not initialized the return of this function is
* 1 (Privilege only) as it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_is_periph_priv_only(struct ppc_sse200_dev_t* dev,
uint8_t periph);
/**
* \brief Enables PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \return Returns error code as specified in \ref ppc_sse200_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum ppc_sse200_error_t ppc_sse200_irq_enable(struct ppc_sse200_dev_t* dev);
/**
* \brief Disables PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_irq_disable(struct ppc_sse200_dev_t* dev);
/**
* \brief Clears PPC interrupt.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void ppc_sse200_clear_irq(struct ppc_sse200_dev_t* dev);
/**
* \brief Returns the PPC interrupt state.
*
* \param[in] dev PPC device \ref ppc_sse200_dev_t
*
* \return Returns 1 if the interrupt is active and otherwise 0.
* If the driver is not initialized the return of this function is
* 0 (not active) as it is the default system configuration.
*
* \note This function doesn't check if dev is NULL.
*/
uint32_t ppc_sse200_irq_state(struct ppc_sse200_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __PPC_SSE_200_DRV_H__ */

View File

@ -1,755 +0,0 @@
/*
* Copyright (c) 2018-2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
/* Use memcpy */
#include <string.h>
#include "qspi_ip6514e_drv.h"
/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
/** Getter bit manipulation macro */
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
#define WORD_ALIGN_4B_MASK 0x3U /* Mask the first 2 bits */
#define IS_ADDR_ALIGNED(ADDR) (((uint32_t)(ADDR) & (WORD_ALIGN_4B_MASK)) == 0U)
#define BITS_PER_BYTE 8U
#define BITS_PER_WORD 32U
#define CFG_READS true
#define CFG_WRITES false
#define ARG_NOT_USED 0
#define ARG_PTR_NOT_USED NULL
#define DATA_REG_NUMBER 2U
#define DATA_REG_LOWER 0U
#define DATA_REG_UPPER 1U
#define ERROR_VALUE 0xFFFFFFFFU
/**
* \brief QSPI IP6514E register map structure
*/
struct _qspi_ip6514e_reg_map_t {
volatile uint32_t qspi_cfg; /*!< 0x00 (R/W) */
volatile uint32_t device_read_inst; /*!< 0x04 (R/W) */
volatile uint32_t device_write_inst; /*!< 0x08 (R/W) */
volatile uint32_t hidden1[2];
volatile uint32_t device_size; /*!< 0x14 (R/W) */
volatile uint32_t hidden2[3];
volatile uint32_t remap_addr; /*!< 0x24 (R/W) */
volatile uint32_t hidden3[26];
volatile uint32_t flash_cmd_ctrl; /*!< 0x90 (R/W) */
volatile uint32_t flash_cmd_addr; /*!< 0x94 (R/W) */
volatile uint32_t hidden4[2];
volatile uint32_t flash_cmd_read_data_lower; /*!< 0xA0 (R/ ) */
volatile uint32_t flash_cmd_read_data_upper; /*!< 0xA4 (R/ ) */
volatile uint32_t flash_cmd_write_data_lower; /*!< 0xA8 (R/W) */
volatile uint32_t flash_cmd_write_data_upper; /*!< 0xAC (R/W) */
volatile uint32_t hidden5[2];
};
/** QSPI Configuration register description (offset 0x00) */
#define QSPI_CFG_ENABLE_POS 0U
#define QSPI_CFG_ENABLE_ADDR_REMAP_POS 16U
#define QSPI_CFG_BAUD_DIV_POS 19U
#define QSPI_CFG_BAUD_DIV_MIN 2U
#define QSPI_CFG_BAUD_DIV_MAX 32U
#define QSPI_CFG_BAUD_DIV_BITS 4U
#define QSPI_CFG_IDLE_POS 31U
/**
* Device Read/Write Instruction registers description (offset 0x04 and 0x08).
* These values are the same for the Device Read Instruction register at offset
* 0x04 and the Device Write Instruction register at offset 0x08.
*/
#define DEVICE_READ_WRITE_INST_OPCODE_POS 0U
#define DEVICE_READ_INST_INST_TYPE_POS 8U /* Only applies to the Read
* register. */
#define DEVICE_READ_WRITE_INST_ADDR_TYPE_POS 12U
#define DEVICE_READ_WRITE_INST_DATA_TYPE_POS 16U
#define DEVICE_READ_WRITE_INST_MODE_QSPI 2U
#define DEVICE_READ_WRITE_INST_MODE_DSPI 1U
#define DEVICE_READ_WRITE_INST_MODE_SPI 0U
#define DEVICE_READ_WRITE_INST_MODE_BITS 2U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS 24U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS 5U
#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX 31U
/** Device Size Configuration register description (offset 0x14) */
#define DEVICE_SIZE_ADDR_BYTES_POS 0U
#define DEVICE_SIZE_ADDR_BYTES_MIN 1U
#define DEVICE_SIZE_ADDR_BYTES_MAX 16U
#define DEVICE_SIZE_ADDR_BYTES_BITS 4U
#define DEVICE_SIZE_PAGE_BYTES_POS 4U
#define DEVICE_SIZE_PAGE_BYTES_MAX 4095U
#define DEVICE_SIZE_PAGE_BYTES_BITS 12U
/** Flash Command Control register description (offset 0x90) */
#define FLASH_CMD_CTRL_EXECUTE_POS 0U
#define FLASH_CMD_CTRL_BUSY_POS 1U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_POS 7U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_MAX 31U
#define FLASH_CMD_CTRL_DUMMY_CYCLES_BITS 5U
#define FLASH_CMD_CTRL_WRITE_BYTES_POS 12U
#define FLASH_CMD_CTRL_WRITE_BYTES_MAX 8U
#define FLASH_CMD_CTRL_WRITE_BYTES_BITS 3U
#define FLASH_CMD_CTRL_WRITE_ENABLE_POS 15U
#define FLASH_CMD_CTRL_ADDR_BYTES_POS 16U
#define FLASH_CMD_CTRL_ADDR_BYTES_MAX 4U
#define FLASH_CMD_CTRL_ADDR_BYTES_BITS 2U
#define FLASH_CMD_CTRL_ADDR_ENABLE_POS 19U
#define FLASH_CMD_CTRL_READ_BYTES_POS 20U
#define FLASH_CMD_CTRL_READ_BYTES_MAX 8U
#define FLASH_CMD_CTRL_READ_BYTES_BITS 3U
#define FLASH_CMD_CTRL_READ_ENABLE_POS 23U
#define FLASH_CMD_CTRL_OPCODE_POS 24U
/** Default register values of the QSPI Flash controller */
#define QSPI_CFG_REG_RESET_VALUE (0x80080080U)
#define DEVICE_READ_INSTR_REG_RESET_VALUE (0x080220EBU)
#define DEVICE_WRITE_INSTR_REG_RESET_VALUE (0x00000002U)
#define DEVICE_SIZE_CFG_REG_RESET_VALUE (0x00101002U)
#define REMAP_ADDR_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_CONTROL_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_ADDRESS_REG_RESET_VALUE (0x00000000U)
#define FLASH_CMD_WRITE_DATA_REG_RESET_VALUE (0x00000000U)
/**
* \brief Change specific bits in a 32 bits word.
*
* \param[in,out] word Pointer of the word to change
* \param[in] bits bits_length bits to put at bits_pos in the word
* pointed
* \param[in] bits_length Number of bits to change
* \param[in] bits_pos Position of the bits to change
*
* \note This function will do nothing if the parameters given are incorret:
* * word is NULL
* * bits_length + bits_pos > 32
* * bits_length is 0
*/
static void change_bits_in_word(volatile uint32_t *word,
uint32_t bits,
uint32_t bits_length,
uint32_t bits_pos)
{
uint32_t mask;
if ((word == NULL) ||
((bits_length + bits_pos) > BITS_PER_WORD) ||
(bits_length == 0U)) {
/* Silently fail */
return;
}
/* Change all the bits */
if (bits_length == BITS_PER_WORD) {
*word = bits;
return;
}
mask = ((1U << bits_length) - 1);
/*
* We change the bits in three steps:
* - clear bits_length bits with zeroes at bits_pos in the word
* - mask bits in case it contains more than bits_length bits
* - set the new bits in the cleared word
* Because the data pointed by word is only read once, the data will still
* be coherent after an interruption that changes it.
*/
*word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
}
/**
* \brief Configure reads or writes commands for direct operations.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Read/write opcode that will be used for every
* direct read/write
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering
* the command, this value must be between 0 and 31
* (both included)
* \param[in] is_reads_cfg true to configure direct reads, false to configure
* direct writes
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
static enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles,
bool is_reads_cfg)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Select the good register address if we want to configure reads or writes.
*/
volatile uint32_t *device_read_write_inst_reg = is_reads_cfg ?
&(reg_map->device_read_inst) :
&(reg_map->device_write_inst);
uint32_t device_read_write_inst_reg_copy = *device_read_write_inst_reg;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (dummy_cycles > DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&device_read_write_inst_reg_copy,
(uint32_t)opcode,
BITS_PER_BYTE,
DEVICE_READ_WRITE_INST_OPCODE_POS);
change_bits_in_word(&device_read_write_inst_reg_copy,
dummy_cycles,
DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS,
DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS);
*device_read_write_inst_reg = device_read_write_inst_reg_copy;
return QSPI_IP6514E_ERR_NONE;
}
/**
* \brief Given the public SPI mode enumeration, returns the private value it
* maps to in the register field.
*
* \param[in] spi_mode Read/write opcode that will be used for every direct
* read/write
*
* \return Return the correct DEVICE_READ_WRITE_INST_MODE value.
*/
static uint32_t spi_mode_field_value(enum qspi_ip6514e_spi_mode_t spi_mode)
{
switch (spi_mode) {
case QSPI_IP6514E_SPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_SPI;
case QSPI_IP6514E_DSPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_DSPI;
case QSPI_IP6514E_QSPI_MODE:
return DEVICE_READ_WRITE_INST_MODE_QSPI;
default:
return ERROR_VALUE;
}
}
bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_IDLE_POS);
}
bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
}
enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
struct qspi_ip6514e_dev_t* dev,
uint32_t div)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
/* div should be an even number. */
if (((div & 1U) == 1) ||
(div < QSPI_CFG_BAUD_DIV_MIN) ||
(div > QSPI_CFG_BAUD_DIV_MAX)) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/*
* The div value (between 2 and 32) needs to be stored in the register on a
* 4 bits field.
*/
change_bits_in_word(&(reg_map->qspi_cfg),
(div / 2) - 1,
QSPI_CFG_BAUD_DIV_BITS,
QSPI_CFG_BAUD_DIV_POS);
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
struct qspi_ip6514e_dev_t* dev,
enum qspi_ip6514e_spi_mode_t inst_type,
enum qspi_ip6514e_spi_mode_t addr_type,
enum qspi_ip6514e_spi_mode_t data_type)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
uint32_t inst_spi_mode, addr_spi_mode, data_spi_mode;
/*
* A local copy of the Device Read Instruction and Device Write Instruction
* registers is used to limit APB accesses.
*/
uint32_t device_read_inst_cpy = reg_map->device_read_inst;
uint32_t device_write_inst_cpy = reg_map->device_write_inst;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
/*
* First check that the instruction mode is not SPI. If that is the case,
* the address and data mode register fields become DO NOT CARE.
*/
inst_spi_mode = spi_mode_field_value(inst_type);
if (inst_spi_mode == ERROR_VALUE) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (inst_type != QSPI_IP6514E_SPI_MODE) {
change_bits_in_word(&(reg_map->device_read_inst),
inst_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_INST_INST_TYPE_POS);
return QSPI_IP6514E_ERR_NONE;
}
/* Now check and set address and data modes. */
addr_spi_mode = spi_mode_field_value(addr_type);
data_spi_mode = spi_mode_field_value(data_type);
if ((addr_spi_mode == ERROR_VALUE) || (data_spi_mode == ERROR_VALUE)) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* Change the Device Read Instruction register. */
change_bits_in_word(&device_read_inst_cpy,
inst_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_INST_INST_TYPE_POS);
change_bits_in_word(&device_read_inst_cpy,
addr_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
change_bits_in_word(&device_read_inst_cpy,
data_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
/* Change the Device Write Instruction register. */
change_bits_in_word(&device_write_inst_cpy,
addr_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
change_bits_in_word(&device_write_inst_cpy,
data_spi_mode,
DEVICE_READ_WRITE_INST_MODE_BITS,
DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
/* Save the changes. */
reg_map->device_read_inst = device_read_inst_cpy;
reg_map->device_write_inst = device_write_inst_cpy;
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles)
{
return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_READS);
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles)
{
return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_WRITES);
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
struct qspi_ip6514e_dev_t* dev,
uint32_t page_size)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (page_size > DEVICE_SIZE_PAGE_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&(reg_map->device_size),
page_size,
DEVICE_SIZE_PAGE_BYTES_BITS,
DEVICE_SIZE_PAGE_BYTES_POS);
return QSPI_IP6514E_ERR_NONE;
}
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
struct qspi_ip6514e_dev_t* dev,
uint32_t bytes_number)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/*
* Wait for the Serial Interface and QSPI pipeline to be IDLE when
* all low level synchronization has been done.
*/
while(!qspi_ip6514e_is_idle(dev));
if (bytes_number < DEVICE_SIZE_ADDR_BYTES_MIN ||
bytes_number > DEVICE_SIZE_ADDR_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&(reg_map->device_size),
bytes_number - 1,
DEVICE_SIZE_ADDR_BYTES_BITS,
DEVICE_SIZE_ADDR_BYTES_POS);
return QSPI_IP6514E_ERR_NONE;
}
void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Save the enable state to restore it after. */
bool is_enabled = qspi_ip6514e_is_enabled(dev);
if (is_enabled) {
qspi_ip6514e_disable(dev);
}
reg_map->remap_addr = offset;
SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
if (is_enabled) {
qspi_ip6514e_enable(dev);
}
}
void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Save the enable state to restore it after. */
bool is_enabled = qspi_ip6514e_is_enabled(dev);
if (is_enabled) {
qspi_ip6514e_disable(dev);
}
CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
if (is_enabled) {
qspi_ip6514e_enable(dev);
}
}
void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* Restore the default value of the QSPI Configuration register. */
reg_map->qspi_cfg = QSPI_CFG_REG_RESET_VALUE;
/* Restore the default value of the Device R/W Instruction registers. */
reg_map->device_read_inst = DEVICE_READ_INSTR_REG_RESET_VALUE;
reg_map->device_write_inst = DEVICE_WRITE_INSTR_REG_RESET_VALUE;
/* Restore the default value of the Device Size Configuration register. */
reg_map->device_size = DEVICE_SIZE_CFG_REG_RESET_VALUE;
/* Restore the default value of the Remap Address register. */
reg_map->remap_addr = REMAP_ADDR_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Control register. */
reg_map->flash_cmd_ctrl = FLASH_CMD_CONTROL_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Address register. */
reg_map->flash_cmd_addr = FLASH_CMD_ADDRESS_REG_RESET_VALUE;
/* Restore the default value of the Flash Command Write Data registers. */
reg_map->flash_cmd_write_data_lower = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
reg_map->flash_cmd_write_data_upper = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
/*
* This function does not affect the Flash Command Read Data registers
* which are completely Read-Only.
*/
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
struct _qspi_ip6514e_reg_map_t *reg_map =
(struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
/* To limit APB accesses, we set this reg up locally before */
uint32_t flash_cmd_ctrl = 0U;
bool read_requested = ((read_data != NULL) && (read_len != 0));
bool write_requested = ((write_data != NULL) && (write_len != 0));
bool addr_requested = (addr_bytes_number != 0);
/*
* To prevent unaligned and byte or halfbyte accesses to the APB registers,
* a word aligned buffer is used to temporary transfer the data before doing
* word accesses on these registers from that buffer.
*/
uint32_t data_regs[DATA_REG_NUMBER] = {0};
if (read_len > FLASH_CMD_CTRL_READ_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (write_len > FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (addr_bytes_number > FLASH_CMD_CTRL_ADDR_BYTES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (dummy_cycles > FLASH_CMD_CTRL_DUMMY_CYCLES_MAX) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
if (read_requested && write_requested) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
change_bits_in_word(&flash_cmd_ctrl,
(uint32_t)opcode,
BITS_PER_BYTE,
FLASH_CMD_CTRL_OPCODE_POS);
/* Enable read if requested */
if (read_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_READ_ENABLE_POS);
change_bits_in_word(&flash_cmd_ctrl,
read_len - 1,
FLASH_CMD_CTRL_READ_BYTES_BITS,
FLASH_CMD_CTRL_READ_BYTES_POS);
}
/* Enable write if requested */
if (write_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_WRITE_ENABLE_POS);
change_bits_in_word(&flash_cmd_ctrl,
write_len - 1,
FLASH_CMD_CTRL_WRITE_BYTES_BITS,
FLASH_CMD_CTRL_WRITE_BYTES_POS);
if (IS_ADDR_ALIGNED(write_data) && IS_ADDR_ALIGNED(write_len)) {
/*
* Optimised case when write_data is word aligned and write_len is
* 4 or 8.
*/
reg_map->flash_cmd_write_data_lower = *(uint32_t *)write_data;
if (write_len == FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
reg_map->flash_cmd_write_data_upper =
*((uint32_t *)write_data + 1);
}
} else {
/*
* data_regs is used as a buffer to only do unaligned access on the
* AHB bus and word aligned accesses to the APB registers.
*/
memcpy((void *)data_regs, write_data, write_len);
/*
* Only write_len bytes will be written even if both data registers
* are written.
*/
reg_map->flash_cmd_write_data_lower = data_regs[DATA_REG_LOWER];
reg_map->flash_cmd_write_data_upper = data_regs[DATA_REG_UPPER];
}
}
/* Enable the address if requested */
if (addr_requested) {
SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_ADDR_ENABLE_POS);
reg_map->flash_cmd_addr = addr;
change_bits_in_word(&flash_cmd_ctrl,
addr_bytes_number - 1,
FLASH_CMD_CTRL_ADDR_BYTES_BITS,
FLASH_CMD_CTRL_ADDR_BYTES_POS);
}
/* Put dummy cycles number */
change_bits_in_word(&flash_cmd_ctrl,
dummy_cycles,
FLASH_CMD_CTRL_DUMMY_CYCLES_BITS,
FLASH_CMD_CTRL_DUMMY_CYCLES_POS);
/* Copy the Flash Command Control register and execute the command */
reg_map->flash_cmd_ctrl = flash_cmd_ctrl;
SET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_EXECUTE_POS);
/* Wait for termination */
while (GET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_BUSY_POS));
/*
* Recolt the read data if it was requested. read_len validity has already
* been verified at this point.
*/
if (read_requested) {
if (IS_ADDR_ALIGNED(read_data) && IS_ADDR_ALIGNED(read_len)) {
/*
* Optimised case when read_data is word aligned and read_len is
* 4 or 8.
*/
*(uint32_t *)read_data = reg_map->flash_cmd_read_data_lower;
if (read_len == FLASH_CMD_CTRL_READ_BYTES_MAX) {
*((uint32_t *)read_data + 1) =
reg_map->flash_cmd_read_data_upper;
}
} else {
/*
* Only read_len bytes have been written even if both data registers
* are written.
*/
data_regs[DATA_REG_LOWER] = reg_map->flash_cmd_read_data_lower;
data_regs[DATA_REG_UPPER] = reg_map->flash_cmd_read_data_upper;
/*
* data_regs is used as a buffer to only do unaligned access on the
* AHB bus and word aligned accesses to the APB registers.
*/
memcpy(read_data, (void *)data_regs, read_len);
}
}
return QSPI_IP6514E_ERR_NONE;
}
void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode)
{
/*
* No read/write data, no address, no dummy cycles.
* Given the arguments, this function can not fail.
*/
(void)qspi_ip6514e_send_cmd(dev,
opcode,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
ARG_NOT_USED,
ARG_NOT_USED,
0);
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
/* Read arguments are expected */
if (read_data == ARG_PTR_NOT_USED || read_len == ARG_NOT_USED) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* No write data */
return qspi_ip6514e_send_cmd(dev,
opcode,
read_data,
read_len,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
addr,
addr_bytes_number,
dummy_cycles);
}
enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles)
{
/* Write arguments are expected */
if (write_data == ARG_PTR_NOT_USED || write_len == ARG_NOT_USED) {
return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
}
/* No read data, no dummy cycles */
return qspi_ip6514e_send_cmd(dev,
opcode,
ARG_PTR_NOT_USED,
ARG_NOT_USED,
write_data,
write_len,
addr,
addr_bytes_number,
dummy_cycles);
}

View File

@ -1,416 +0,0 @@
/*
* Copyright (c) 2018 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file qspi_ip6514e_drv.h
* \brief Driver for Cadence QSPI Flash Controller IP.
* There are two ways to communicate with the flash memory device:
* - issue AHB requests for direct read and writes in the Flash memory
* mapped address zone. The commands used for those can be configured
* by the driver
* - send a command to the device to access his internal registers and
* do other operations like erasing a sector
* At reset, the QSPI controller will work in a default mode which will
* allow to do basic commands. It should be configured with the
* flash memory device specifications for optimal use for commands and
* direct reads/writes. Here is an example of configuration:
* - send command to activate QSPI mode on the flash memory device
* - send command to change dummy cycles on the flash memory device
* - check if any operation is ungoing
* - disable the QSPI controller
* - change the baud rate divisor
* - activate the QSPI mode on the controller
* - change the dummy cycles number and opcode for reads/writes
* - change the number of bytes per page
* - change the number of address bytes
* - activate the QSPI controller
*
* Warning: none of the functions declared here check if the dev
* argument points to NULL.
*/
#ifndef __QSPI_IP6514E_DRV_H__
#define __QSPI_IP6514E_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Cadence QSPI IP6514E error enumeration types
*/
enum qspi_ip6514e_error_t {
QSPI_IP6514E_ERR_NONE,
QSPI_IP6514E_ERR_WRONG_ARGUMENT,
QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
QSPI_IP6514E_ERR_READ_IN_PROGRESS,
QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
/* Any new error should be added to the enumeration type error of
* the corresponding Flash device library as well.
*/
};
/**
* \brief Cadence QSPI IP6514E SPI modes
*/
enum qspi_ip6514e_spi_mode_t {
QSPI_IP6514E_SPI_MODE,
/*!< Use 1 line for Instruction, Address and Data */
QSPI_IP6514E_DSPI_MODE,
/*!< Use 2 lines for Instruction, Address and Data */
QSPI_IP6514E_QSPI_MODE,
/*!< Use 4 lines for Instruction, Address and Data */
};
/**
* \brief Cadence QSPI IP6514E device configuration structure
*/
struct qspi_ip6514e_dev_cfg_t {
const uint32_t base; /*!< QSPI IP6514E base address */
/*
* If not all the AHB wires are connected to the QSPI Flash Controller the
* driver can still access all of the Flash memory. The bits of this value
* should be put to 1 for every wire that is connected. Set it to
* 0xFFFFFFFFU if all AHB address wires are connected to the
* QSPI Flash Controller.
*/
uint32_t addr_mask;
};
/**
* \brief Cadence QSPI IP6514E device structure
*/
struct qspi_ip6514e_dev_t {
const struct qspi_ip6514e_dev_cfg_t* const cfg;
/*!< QSPI IP6514E configuration */
};
/**
* \brief Check if the controller is idle.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \return true if the controller is idle, false otherwise.
*/
bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Check if the controller is enabled.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \return true if the controller is enabled, false otherwise.
*/
bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Disable the QSPI controller.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*/
void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Enable the QSPI controller.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*/
void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Change the baud rate divisor.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] div Baud rate divisor value. It can only be an even number
* between 2 and 32 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI frequency is calculated dividing the QSPI controller clock by
* this divisor. Please check Flash memory device specifications to know
* the maximal frequency that can be used.
* \note The QSPI controller should be disabled before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
struct qspi_ip6514e_dev_t* dev,
uint32_t div);
/**
* \brief Set SPI mode for instruction, address and data.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] inst_type SPI mode to use for the instruction part of the command
* \param[in] addr_type SPI mode to use for the address part of the command
* \param[in] data_type SPI mode to use for the data part of the command
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note Changing this setting will affect commands and direct operations.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
struct qspi_ip6514e_dev_t* dev,
enum qspi_ip6514e_spi_mode_t inst_type,
enum qspi_ip6514e_spi_mode_t addr_type,
enum qspi_ip6514e_spi_mode_t data_type);
/**
* \brief Configure read commands for direct reads.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Read opcode that will be used for every direct read
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
* command, this value must be between 0 and 31
* (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles);
/**
* \brief Configure write commands for direct writes.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Write opcode that will be used for every direct write
* \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
* command, this value must be between 0 and 31
* (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
uint32_t dummy_cycles);
/**
* \brief Change the number of bytes per device page.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] page_size Number of bytes per device page, must be between 0
* and 4095 (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note This function will affect direct reads/writes.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
struct qspi_ip6514e_dev_t* dev,
uint32_t page_size);
/**
* \brief Change the number of device address bytes.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] bytes_number Number of device address bytes, must be between 1
* and 16 (both included)
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note The QSPI controller should be idle before calling this function.
* \note This function will affect direct reads/writes.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
struct qspi_ip6514e_dev_t* dev,
uint32_t bytes_number);
/**
* \brief Remap the incoming AHB address with an offset for direct accesses.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] offset Offset that will be added to the incoming AHB address to
* access the Flash memory
*
* \note This function will only affect direct reads/writes.
* \note This function does not check if the resulting address is out of memory
* bounds.
*/
void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset);
/**
* \brief Disable AHB address remapping for direct accesses.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \note This function will disable the controller if it is not already
* disabled and enable it again (if it was).
* \note This function will only affect direct reads/writes.
*/
void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Restore the default value of the QSPI controller registers.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
*
* \note The QSPI controller should be disabled before calling this function.
*/
void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev);
/**
* \brief Send a command to the flash memory device using the Software Triggered
* Instruction Generator (STIG).
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[out] read_data Pointer to a memory zone where the read_len
* bytes read will be written to. If no data is to
* be read for the command,
* this argument should be NULL.
* \param[in] read_len Number of bytes to read for the command. If
* no bytes are to be read, use 0 for argument
* otherwise between 1 and 8 bytes (both
* included) can be read.
* \param[in] write_data Pointer to a memory zone where are
* located the write_len bytes to write for
* this command. If no bytes are to be written,
* use NULL as argument.
* \param[in] write_len Number of bytes to write for the command. If
* no bytes are to be written, use 0 for
* argument otherwise between 1 and 8 bytes
* (both included) can be written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
/**
* \brief Send a simple command to the flash memory device using the Software
* Triggered Instruction Generator (STIG) with no data arguments.
* This command can be used for example to send the WRITE ENABLE command.
*
* \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
uint8_t opcode);
/**
* \brief Send a read command to the flash memory device using the Software
* Triggered Instruction Generator (STIG). This command can be used to
* read Flash memory data or registers.
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[out] read_data Pointer to a memory zone where the
* read_len bytes read will be written to.
* \param[in] read_len Number of bytes to read for the command.
* Between 1 and 8 bytes (both included) can be
* read.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
void *read_data,
uint32_t read_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
/**
* \brief Send a write command to the flash memory device using the Software
* Triggered Instruction Generator (STIG). This command can be used to
* write Flash memory or registers.
*
* \param[in] dev QSPI IP6514E device struct
* \ref qspi_ip6514e_dev_t
* \param[in] opcode Opcode for the command.
* \param[in] write_data Pointer to a memory zone where are
* located the write_len bytes to write for
* this command.
* \param[in] write_len Number of bytes to write for the command.
* Between 1 and 8 bytes (both included) can be
* written.
* \param[in] addr Address used for the command
* \param[in] addr_bytes_number Number of address bytes for this command.
* If an address is not needed for the command,
* use 0 for argument, otherwise between 1 and
* 4 bytes (both included) can be used.
* \param[in] dummy_cycles Number of dummy cycles required for the
* command, between 0 and 31 (both included).
*
* \return Returns error code as specified in \ref qspi_ip6514e_error_t
*
* \note Check the flash memory device specifications for the possible opcodes
* that can be used and the other informations needed for this function.
* \note The SPI mode used for this command is the one set with the
* \ref qspi_ip6514e_activate_qspi_mode function or the default one.
*/
enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
struct qspi_ip6514e_dev_t* dev,
uint8_t opcode,
const void *write_data,
uint32_t write_len,
uint32_t addr,
uint32_t addr_bytes_number,
uint32_t dummy_cycles);
#ifdef __cplusplus
}
#endif
#endif /* __QSPI_IP6514E_DRV_H__ */

View File

@ -1,138 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2020 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device.h"
#include "flash_layout.h"
#include "flash_api.h"
#if DEVICE_FLASH
#define FLASH_DEV MT25QL_DEV_S
int32_t flash_init(flash_t *obj)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
qspi_ip6514e_enable(FLASH_DEV.controller);
/* Configure QSPI Flash controller to operate in single SPI mode and
* to use fast Flash commands */
err = mt25ql_config_mode(&FLASH_DEV, MT25QL_FUNC_STATE_FAST);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_free(flash_t *obj)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
/* Restores the QSPI Flash controller and MT25QL to reset state */
err = mt25ql_restore_reset_state(&FLASH_DEV);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
address -= FLASH_DEV.direct_access_start_addr;
err = mt25ql_erase(&FLASH_DEV, address, MT25QL_ERASE_SUBSECTOR_4K);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_read(flash_t *obj, uint32_t address,
uint8_t *data, uint32_t size)
{
(void)obj;
enum mt25ql_error_t err = MT25QL_ERR_NONE;
address -= FLASH_DEV.direct_access_start_addr;
err = mt25ql_command_read(&FLASH_DEV, address, data, size);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{
(void)(obj);
enum mt25ql_error_t err = MT25QL_ERR_NONE;
address -= FLASH_DEV.direct_access_start_addr;
err = mt25ql_command_write(&FLASH_DEV, address, data, size);
if (err != MT25QL_ERR_NONE) {
return -1;
}
return 0;
}
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
{
(void)(obj);
if ((address >= S_QSPI_ALIAS_BASE) && (address < S_QSPI_ALIAS_BASE + QSPI_FLASH_TOTAL_SIZE)) {
return SUBSECTOR_4KB;
}
return MBED_FLASH_INVALID_SIZE;
}
uint32_t flash_get_page_size(const flash_t *obj)
{
(void)(obj);
return FLASH_PAGE_SIZE;
}
uint32_t flash_get_start_address(const flash_t *obj)
{
(void)(obj);
return S_QSPI_ALIAS_BASE;
}
uint32_t flash_get_size(const flash_t *obj)
{
(void)(obj);
return QSPI_FLASH_TOTAL_SIZE;
}
uint8_t flash_get_erase_value(const flash_t *obj)
{
(void)obj;
return 0xFF;
}
#endif // DEVICE_FLASH

View File

@ -1,102 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file implements APIS defined in hal/gpio_api.h
*/
#include <stddef.h>
#include "gpio_api.h"
#include "pinmap.h"
#include "objects.h"
#include "mbed_error.h"
uint32_t gpio_set(PinName pin)
{
pin_function(pin, (int)PRIMARY_FUNC);
/* Return the correct mask of the given PIN */
return (1 << GPIO_PIN_NUMBER(pin));
}
void gpio_init(gpio_t *obj, PinName pin)
{
struct gpio_cmsdk_dev_t *gpio_dev;
obj->pin_num = (uint32_t)NC;
if (pin >= PA0 && pin <= PA15) {
#ifdef GPIO0_CMSDK_DEV
gpio_dev = &GPIO0_CMSDK_DEV;
#else
error("GPIO associated with expansion pin %d, is disabled", pin);
/* error() calls exit() eventually, but to be safe we return here */
return;
#endif
gpio_cmsdk_init(gpio_dev);
obj->gpio_dev = gpio_dev;
obj->pin_num = pin;
/* GPIO is input by default */
obj->direction = PIN_INPUT;
return;
}
error("pin %d is not a GPIO", pin);
}
void gpio_mode(gpio_t *obj, PinMode mode)
{
pin_mode(obj->pin_num, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction)
{
enum gpio_cmsdk_direction_t pin_dir =
(direction == PIN_INPUT) ? GPIO_CMSDK_INPUT : GPIO_CMSDK_OUTPUT;
if (gpio_cmsdk_pin_config(obj->gpio_dev, obj->pin_num, pin_dir,
GPIO_CMSDK_MAIN_FUNC) == GPIO_CMSDK_ERR_NONE) {
obj->direction = direction;
}
}
int gpio_is_connected(const gpio_t *obj)
{
if (obj->pin_num == (uint32_t)NC) {
return 0;
} else {
return 1;
}
}
void gpio_write(gpio_t *obj, int value)
{
enum gpio_cmsdk_error_t ret =
gpio_cmsdk_pin_write(obj->gpio_dev, obj->pin_num, (uint32_t)value);
if (ret) {
error("Can not write pin %d", obj->pin_num);
}
}
int gpio_read(gpio_t *obj)
{
uint32_t data = 0;
(void)gpio_cmsdk_pin_read(obj->gpio_dev, obj->pin_num, &data);
return (int)data;
}

View File

@ -1,115 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file implements APIS defined in hal/pinmap.h
*
* Pin functions are not available in interrupt context, because the
* NS side is only allowed to call TF-M secure functions (veneers) from
* the NS Thread mode.
*
*/
#include "mbed_assert.h"
#include "mbed_error.h"
#include "device_definition.h"
#include "objects.h"
#include "pinmap.h"
#include "musca_b1_scc_drv.h"
/**
* \brief Translates between different pin mode enums
*
* \param[in] mode Pin mode to translate \ref PinMode
*
* \return Translated pin mode \ref pinmode_select_t
*/
static enum pinmode_select_t translate_pinmode(PinMode mode)
{
switch (mode) {
case PullNone:
return PINMODE_NONE;
case PullDown:
return PINMODE_PULL_DOWN;
case PullUp:
return PINMODE_PULL_UP;
default:
return PINMODE_NONE;
}
}
/**
* \brief Configures the GPIO pin and sets the alternate function
*
* \param[in] pin GPIO pin number \ref PinName
* \param[in] function Alternate function to set \ref PinFunction
*/
void pin_function(PinName pin, int function)
{
enum gpio_altfunc_t flags;
uint32_t result = 0;
MBED_ASSERT(pin != NC);
switch (function) {
case PRIMARY_FUNC:
flags = GPIO_MAIN_FUNC;
break;
case ALTERNATE_FUNC_1:
flags = GPIO_ALTFUNC_1;
break;
case ALTERNATE_FUNC_2:
flags = GPIO_ALTFUNC_2;
break;
case ALTERNATE_FUNC_3:
flags = GPIO_ALTFUNC_3;
break;
default:
return;
}
#ifdef MUSCA_B1_SCC_DEV
result = musca_b1_scc_set_alt_func(&MUSCA_B1_SCC_DEV, flags, (1u<<pin));
if (result != SCC_ERR_NONE) {
error("Can not set pin alt func %d", pin);
}
#else
error("SCC device associated with expansion pin %d, is disabled", pin);
#endif
}
/**
* \brief Sets pin mode for the given GPIO pin
*
* \param[in] pin GPIO pin number \ref PinName
* \param[in] mode Pin mode to set \ref PinMode
*/
void pin_mode(PinName pin, PinMode mode)
{
uint32_t result = 0;
MBED_ASSERT(pin != NC);
#ifdef MUSCA_B1_SCC_DEV
result = musca_b1_scc_set_pinmode(&MUSCA_B1_SCC_DEV, (1u<<pin),
translate_pinmode(mode));
if (result != SCC_ERR_NONE) {
error("Can not set pin mode %d", pin);
}
#else
error("SCC device associated with expansion pin %d, is disabled", pin);
#endif
}

View File

@ -1,324 +0,0 @@
/*
* Copyright (c) 2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdio.h>
#include "platform/include/tfm_spm_hal.h"
#include "spm_api.h"
#include "spm_db.h"
#include "tfm_platform_core_api.h"
#include "target_cfg.h"
#include "Driver_MPC.h"
#include "mpu_armv8m_drv.h"
#include "region_defs.h"
#include "secure_utilities.h"
/* Import MPC driver */
extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC;
/* Get address of memory regions to configure MPU */
extern const struct memory_region_limits memory_regions;
struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
void tfm_spm_hal_init_isolation_hw(void)
{
/* Configures non-secure memory spaces in the target */
sau_and_idau_cfg();
mpc_init_cfg();
ppc_init_cfg();
}
void tfm_spm_hal_configure_default_isolation(
const struct tfm_spm_partition_platform_data_t *platform_data)
{
if (platform_data) {
if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
ppc_configure_to_secure(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
}
}
#if TFM_LVL != 1
#define MPU_REGION_VENEERS 0
#define MPU_REGION_TFM_UNPRIV_CODE 1
#define MPU_REGION_TFM_UNPRIV_DATA 2
#define MPU_REGION_NS_DATA 3
#define PARTITION_REGION_RO 4
#define PARTITION_REGION_RW_STACK 5
#define PARTITION_REGION_PERIPH 6
#define PARTITION_REGION_SHARE 7
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
static enum spm_err_t tfm_spm_mpu_init(void)
{
struct mpu_armv8m_region_cfg_t region_cfg;
mpu_armv8m_clean(&dev_mpu_s);
/* Veneer region */
region_cfg.region_nr = MPU_REGION_VENEERS;
region_cfg.region_base = memory_regions.veneer_base;
region_cfg.region_limit = memory_regions.veneer_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged code region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_CODE;
region_cfg.region_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
region_cfg.region_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged data region */
region_cfg.region_nr = MPU_REGION_TFM_UNPRIV_DATA;
region_cfg.region_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$RW$$Base);
region_cfg.region_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_RO_DATA, $$ZI$$Limit);
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
/* TFM Core unprivileged non-secure data region */
region_cfg.region_nr = MPU_REGION_NS_DATA;
region_cfg.region_base = NS_DATA_START;
region_cfg.region_limit = NS_DATA_LIMIT;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
enum spm_err_t tfm_spm_hal_partition_sandbox_config(
const struct tfm_spm_partition_memory_data_t *memory_data,
const struct tfm_spm_partition_platform_data_t *platform_data)
{
/* This function takes a partition id and enables the
* SPM partition for that partition
*/
struct mpu_armv8m_region_cfg_t region_cfg;
mpu_armv8m_disable(&dev_mpu_s);
/* Configure Regions */
if (memory_data->ro_start) {
/* RO region */
region_cfg.region_nr = PARTITION_REGION_RO;
region_cfg.region_base = memory_data->ro_start;
region_cfg.region_limit = memory_data->ro_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_OK;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
!= MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
}
/* RW, ZI and stack as one region */
region_cfg.region_nr = PARTITION_REGION_RW_STACK;
region_cfg.region_base = memory_data->rw_start;
region_cfg.region_limit = memory_data->stack_top;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg) != MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
if (platform_data) {
/* Peripheral */
region_cfg.region_nr = PARTITION_REGION_PERIPH;
region_cfg.region_base = platform_data->periph_start;
region_cfg.region_limit = platform_data->periph_limit;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
!= MPU_ARMV8M_OK) {
return SPM_ERR_INVALID_CONFIG;
}
ppc_en_secure_unpriv(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(
const struct tfm_spm_partition_memory_data_t *memory_data,
const struct tfm_spm_partition_platform_data_t *platform_data)
{
/* This function takes a partition id and disables the
* SPM partition for that partition
*/
if (platform_data) {
/* Peripheral */
ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,
platform_data->periph_ppc_loc);
}
mpu_armv8m_disable(&dev_mpu_s);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RO);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_RW_STACK);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_PERIPH);
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return SPM_ERR_OK;
}
/**
* Set share region to which the partition needs access
*/
enum spm_err_t tfm_spm_hal_set_share_region(
enum tfm_buffer_share_region_e share)
{
struct mpu_armv8m_region_cfg_t region_cfg;
enum spm_err_t res = SPM_ERR_INVALID_CONFIG;
uint32_t scratch_base =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
uint32_t scratch_limit =
(uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
mpu_armv8m_disable(&dev_mpu_s);
if (share == TFM_BUFFER_SHARE_DISABLE) {
mpu_armv8m_region_disable(&dev_mpu_s, PARTITION_REGION_SHARE);
} else {
region_cfg.region_nr = PARTITION_REGION_SHARE;
region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
switch (share) {
case TFM_BUFFER_SHARE_SCRATCH:
/* Use scratch area for SP-to-SP data sharing */
region_cfg.region_base = scratch_base;
region_cfg.region_limit = scratch_limit;
res = SPM_ERR_OK;
break;
case TFM_BUFFER_SHARE_NS_CODE:
region_cfg.region_base = memory_regions.non_secure_partition_base;
region_cfg.region_limit = memory_regions.non_secure_partition_limit;
/* Only allow read access to NS code region and keep
* exec.never attribute
*/
region_cfg.attr_access = MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
res = SPM_ERR_OK;
break;
default:
/* Leave res to be set to SPM_ERR_INVALID_CONFIG */
break;
}
if (res == SPM_ERR_OK) {
mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg);
}
}
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE);
return res;
}
#endif /* TFM_LVL != 1 */
void tfm_spm_hal_setup_isolation_hw(void)
{
#if TFM_LVL != 1
if (tfm_spm_mpu_init() != SPM_ERR_OK) {
ERROR_MSG("Failed to set up initial MPU configuration! Halting.");
while (1) {
;
}
}
#endif
}
void MPC_Handler(void)
{
/* Clear MPC interrupt flag and pending MPC IRQ */
Driver_CODE_SRAM_MPC.ClearInterrupt();
NVIC_ClearPendingIRQ(S_MPC_COMBINED_IRQn);
/* Print fault message and block execution */
LOG_MSG("Oops... MPC fault!!!");
/* Inform TF-M core that isolation boundary has been violated */
tfm_access_violation_handler();
}
void PPC_Handler(void)
{
/*
* Due to an issue on the FVP, the PPC fault doesn't trigger a
* PPC IRQ which is handled by the PPC_handler.
* In the FVP execution, this code is not execute.
*/
/* Clear PPC interrupt flag and pending PPC IRQ */
ppc_clear_irq();
NVIC_ClearPendingIRQ(S_PPC_COMBINED_IRQn);
/* Print fault message*/
LOG_MSG("Oops... PPC fault!!!");
/* Inform TF-M core that isolation boundary has been violated */
tfm_access_violation_handler();
}
uint32_t tfm_spm_hal_get_ns_VTOR(void)
{
return memory_regions.non_secure_code_start;
}
uint32_t tfm_spm_hal_get_ns_MSP(void)
{
return *((uint32_t *)memory_regions.non_secure_code_start);
}
uint32_t tfm_spm_hal_get_ns_entry_point(void)
{
return *((uint32_t *)(memory_regions.non_secure_code_start+ 4));
}

View File

@ -1,533 +0,0 @@
/*
* Copyright (c) 2018-2020 Arm Limited. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "target_cfg.h"
#include "Driver_MPC.h"
#include "Driver_PPC.h"
#include "platform_description.h"
#include "device_definition.h"
#include "region_defs.h"
#include "tfm_secure_api.h"
#include "mbed_assert.h"
#include "platform_srv_impl.h"
/* Macros to pick linker symbols */
#define REGION(a, b, c) a##b##c
#define REGION_NAME(a, b, c) REGION(a, b, c)
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
/* The section names come from the scatter file */
REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Base);
REGION_DECLARE(Image$$, ER_CODE_CMSE_VENEER, $$Limit);
const struct memory_region_limits memory_regions = {
.non_secure_code_start =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
BL2_HEADER_SIZE,
.non_secure_partition_base =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
.non_secure_partition_limit =
(uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
NS_PARTITION_SIZE - 1,
.veneer_base =
(uint32_t)&REGION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Base),
.veneer_limit =
(uint32_t)&REGION_NAME(Image$$, ER_CODE_CMSE_VENEER, $$Limit),
};
/* Allows software, via SAU, to define the code region as a NSC */
#define NSCCFG_CODENSC 1
/* Import MPC driver */
extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC, Driver_EFLASH0_MPC;
extern ARM_DRIVER_MPC Driver_ISRAM0_MPC, Driver_ISRAM1_MPC;
extern ARM_DRIVER_MPC Driver_ISRAM2_MPC, Driver_ISRAM3_MPC;
/* Import PPC driver */
extern ARM_DRIVER_PPC Driver_APB_PPC0, Driver_APB_PPC1;
extern ARM_DRIVER_PPC Driver_AHB_PPCEXP0;
extern ARM_DRIVER_PPC Driver_APB_PPCEXP0, Driver_APB_PPCEXP1;
/* Define Peripherals NS address range for the platform */
#define PERIPHERALS_BASE_NS_START (0x40000000)
#define PERIPHERALS_BASE_NS_END (0x4FFFFFFF)
/* Enable system reset request for CPU 0 */
#define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 4U)
/* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field,
* otherwise the processor ignores the write.
*/
#define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos))
/* Debug configuration MASKS */
#define DBG_CTRL_MASK_DBGEN (0x01 << 1)
#define DBG_CTRL_MASK_NIDEN (0x01 << 2)
#define DBG_CTRL_MASK_SPIDEN (0x01 << 3)
#define DBG_CTRL_MASK_SPNIDEN (0x01 << 4)
#define DBG_CTRL_ADDR 0x50089E00UL
#define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \
NIDEN_SEL_STATUS | DBGEN_SEL_STATUS)
struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart = {
MUSCA_B1_UART1_NS_BASE,
MUSCA_B1_UART1_NS_BASE + 0xFFF,
PPC_SP_DO_NOT_CONFIGURE,
-1
};
static ARM_DRIVER_PPC *const ppc_bank_drivers[] = {
0, /* AHB PPC0 */
0, /* Reserved */
0, /* Reserved */
0, /* Reserved */
&Driver_AHB_PPCEXP0, /* AHB PPCEXP0 */
0, /* AHB PPCEXP1 */
0, /* AHB PPCEXP2 */
0, /* AHB PPCEXP3 */
&Driver_APB_PPC0, /* APB PPC0 */
&Driver_APB_PPC1, /* APB PPC1 */
0, /* Reserved */
0, /* Reserved */
&Driver_APB_PPCEXP0, /* APB PPCEXP0 */
&Driver_APB_PPCEXP1, /* APB PPCEXP1 */
};
#define PPC_BANK_COUNT \
(sizeof(ppc_bank_drivers)/sizeof(ppc_bank_drivers[0]))
void enable_fault_handlers(void)
{
/* Explicitly set secure fault priority to the highest */
NVIC_SetPriority(SecureFault_IRQn, 0);
/* Enables BUS, MEM, USG and Secure faults */
SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
| SCB_SHCSR_BUSFAULTENA_Msk
| SCB_SHCSR_MEMFAULTENA_Msk
| SCB_SHCSR_SECUREFAULTENA_Msk;
}
void system_reset_cfg(void)
{
struct sysctrl_t *sysctrl = (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
uint32_t reg_value = SCB->AIRCR;
/* Enable system reset request for CPU 0, to be triggered via
* NVIC_SystemReset function.
*/
sysctrl->resetmask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST;
/* Clear SCB_AIRCR_VECTKEY value */
reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk);
/* Enable system reset request only to the secure world */
reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk);
SCB->AIRCR = reg_value;
}
void tfm_spm_hal_init_debug(void)
{
volatile uint32_t *dbg_ctrl_p = (uint32_t*)DBG_CTRL_ADDR;
#if defined(DAUTH_NONE)
*dbg_ctrl_p &= ~(DBG_CTRL_MASK_DBGEN |
DBG_CTRL_MASK_NIDEN |
DBG_CTRL_MASK_SPIDEN |
DBG_CTRL_MASK_SPNIDEN);
#elif defined(DAUTH_NS_ONLY)
*dbg_ctrl_p &= ~(DBG_CTRL_MASK_SPIDEN |
DBG_CTRL_MASK_SPNIDEN);
*dbg_ctrl_p |= DBG_CTRL_MASK_DBGEN |
DBG_CTRL_MASK_NIDEN;
#elif defined(DAUTH_FULL)
*dbg_ctrl_p |= DBG_CTRL_MASK_DBGEN |
DBG_CTRL_MASK_NIDEN |
DBG_CTRL_MASK_SPIDEN |
DBG_CTRL_MASK_SPNIDEN;
#else
#if !defined(DAUTH_CHIP_DEFAULT)
#error "No debug authentication setting is provided."
#endif
/* No need to set any enable bits because the value depends on
* input signals.
*/
(void)dbg_ctrl_p;
#endif
}
/*----------------- NVIC interrupt target state to NS configuration ----------*/
void nvic_interrupt_target_state_cfg()
{
/* Target every interrupt to NS; unimplemented interrupts will be WI */
for (uint8_t i=0; i<sizeof(NVIC->ITNS)/sizeof(NVIC->ITNS[0]); i++) {
NVIC->ITNS[i] = 0xFFFFFFFF;
}
/* Make sure that MPC and PPC are targeted to S state */
NVIC_ClearTargetState(S_MPC_COMBINED_IRQn);
NVIC_ClearTargetState(S_PPC_COMBINED_IRQn);
}
/*----------------- NVIC interrupt enabling for S peripherals ----------------*/
void nvic_interrupt_enable()
{
int32_t ret = ARM_DRIVER_OK;
/* MPC interrupt enabling */
ret |= Driver_EFLASH0_MPC.EnableInterrupt();
ret |= Driver_CODE_SRAM_MPC.EnableInterrupt();
if (ret != ARM_DRIVER_OK) {
MBED_ASSERT("MPC IRQ enable failed!");
}
NVIC_EnableIRQ(S_MPC_COMBINED_IRQn);
/* PPC interrupt enabling */
/* Clear pending PPC interrupts */
/* In the PPC configuration function, we have used the Non-Secure
* Privilege Control Block to grant unprivilged NS access to some
* peripherals used by NS. That triggers a PPC0 exception as that
* register is meant for NS privileged access only. Clear it here
*/
Driver_APB_PPC0.ClearInterrupt();
/* Enable PPC interrupts for APB PPC */
ret |= Driver_APB_PPC0.EnableInterrupt();
ret |= Driver_APB_PPC1.EnableInterrupt();
ret |= Driver_APB_PPCEXP0.EnableInterrupt();
ret |= Driver_APB_PPCEXP1.EnableInterrupt();
if (ret != ARM_DRIVER_OK) {
MBED_ASSERT("PPC IRQ enable failed!");
}
NVIC_EnableIRQ(S_PPC_COMBINED_IRQn);
}
/*------------------- SAU/IDAU configuration functions -----------------------*/
void sau_and_idau_cfg(void)
{
/* Enables SAU */
TZ_SAU_Enable();
/* Configures SAU regions to be non-secure */
SAU->RNR = TFM_NS_REGION_CODE;
SAU->RBAR = (memory_regions.non_secure_partition_base
& SAU_RBAR_BADDR_Msk);
SAU->RLAR = (memory_regions.non_secure_partition_limit
& SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
SAU->RNR = TFM_NS_REGION_DATA;
SAU->RBAR = (NS_DATA_START & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (NS_DATA_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
/* Configures veneers region to be non-secure callable */
SAU->RNR = TFM_NS_REGION_VENEER;
SAU->RBAR = (memory_regions.veneer_base & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (memory_regions.veneer_limit & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk
| SAU_RLAR_NSC_Msk;
/* Configure the peripherals space */
SAU->RNR = TFM_NS_REGION_PERIPH_1;
SAU->RBAR = (PERIPHERALS_BASE_NS_START & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
/* Secondary image partition */
SAU->RNR = TFM_NS_SECONDARY_IMAGE_REGION;
SAU->RBAR = (memory_regions.secondary_partition_base & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (memory_regions.secondary_partition_limit & SAU_RLAR_LADDR_Msk)
| SAU_RLAR_ENABLE_Msk;
/* Allows SAU to define the code region as a NSC */
struct spctrl_def* spctrl = CMSDK_SPCTRL;
spctrl->nsccfg |= NSCCFG_CODENSC;
}
/*------------------- Memory configuration functions -------------------------*/
void mpc_init_cfg(void)
{
ARM_DRIVER_MPC* mpc_data_region0 = &Driver_ISRAM0_MPC;
ARM_DRIVER_MPC* mpc_data_region1 = &Driver_ISRAM1_MPC;
ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
int32_t ret = ARM_DRIVER_OK;
ret |= Driver_EFLASH0_MPC.Initialize();
ret |= Driver_EFLASH0_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
memory_regions.non_secure_partition_limit,
ARM_MPC_ATTR_NONSECURE);
/* Secondary image region */
ret |= Driver_EFLASH0_MPC.ConfigRegion(memory_regions.secondary_partition_base,
memory_regions.secondary_partition_limit,
ARM_MPC_ATTR_NONSECURE);
ret |= mpc_data_region0->Initialize();
ret |= mpc_data_region0->ConfigRegion(MPC_ISRAM0_RANGE_BASE_S,
MPC_ISRAM0_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
ret |= mpc_data_region1->Initialize();
ret |= mpc_data_region1->ConfigRegion(MPC_ISRAM1_RANGE_BASE_S,
MPC_ISRAM1_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
ret |= mpc_data_region2->Initialize();
ret |= mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_NS,
MPC_ISRAM2_RANGE_LIMIT_NS,
ARM_MPC_ATTR_NONSECURE);
ret |= mpc_data_region3->Initialize();
ret |= mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_NS,
MPC_ISRAM3_RANGE_LIMIT_NS,
ARM_MPC_ATTR_NONSECURE);
if (ret != ARM_DRIVER_OK) {
MBED_ASSERT("MPC init failed!");
}
/* Add barriers to assure the MPC configuration is done before continue
* the execution.
*/
__DSB();
__ISB();
}
void mpc_revert_non_secure_to_secure_cfg(void)
{
ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
int32_t ret = ARM_DRIVER_OK;
ret |= Driver_EFLASH0_MPC.ConfigRegion(MPC_EFLASH0_RANGE_BASE_S,
MPC_EFLASH0_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
ret |= mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_S,
MPC_ISRAM2_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
ret |= mpc_data_region3->ConfigRegion(MPC_ISRAM3_RANGE_BASE_S,
MPC_ISRAM3_RANGE_LIMIT_S,
ARM_MPC_ATTR_SECURE);
if (ret != ARM_DRIVER_OK) {
MBED_ASSERT("MPC revert config failed!");
}
/* Add barriers to assure the MPC configuration is done before continue
* the execution.
*/
__DSB();
__ISB();
}
/*---------------------- PPC configuration functions -------------------------*/
void ppc_init_cfg(void)
{
struct spctrl_def* spctrl = CMSDK_SPCTRL;
int32_t ret = ARM_DRIVER_OK;
/* Grant non-secure access to peripherals in the APB PPC0
* (timer0 and 1, dualtimer, mhu 0 and 1)
*/
ret |= Driver_APB_PPC0.Initialize();
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_TIMER0_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_TIMER1_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_DTIMER_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_MHU0_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPC0.ConfigPeriph(CMSDK_MHU1_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
/* Grant non-secure access for APB MHU0 on EXP0 */
ret |= Driver_APB_PPCEXP0.Initialize();
ret |= Driver_APB_PPCEXP0.ConfigPeriph(MUSCA_B1_CI_MHU0_S_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP0.ConfigPeriph(MUSCA_B1_CI_MHU0_R_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
/* Grant non-secure access for APB peripherals on EXP1 */
ret |= Driver_APB_PPCEXP1.Initialize();
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM0_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM1_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PWM2_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2S_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_UART0_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_UART1_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_AND_NONPRIV);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2C0_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_I2C1_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_SPI_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_GPTIMER_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_RTC_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_PVT_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
ret |= Driver_APB_PPCEXP1.ConfigPeriph(MUSCA_B1_SDIO_APB_PPC_POS,
ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
if (ret != ARM_DRIVER_OK) {
MBED_ASSERT("PPC init failed!");
}
/* Configure the response to a security violation as a
* bus error instead of RAZ/WI
*/
spctrl->secrespcfg |= 1U;
}
void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
{
/* Setting NS flag for peripheral to enable NS access */
ARM_DRIVER_PPC *ppc_driver;
if (bank >= PPC_BANK_COUNT) {
return;
}
ppc_driver = ppc_bank_drivers[bank];
if (ppc_driver) {
ppc_driver->ConfigPeriph(pos, ARM_PPC_NONSECURE_ONLY,
ARM_PPC_PRIV_ONLY);
}
}
void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
{
/* Clear NS flag for peripheral to prevent NS access */
ARM_DRIVER_PPC *ppc_driver;
if (bank >= PPC_BANK_COUNT) {
return;
}
ppc_driver = ppc_bank_drivers[bank];
if (ppc_driver) {
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
ARM_PPC_PRIV_ONLY);
}
}
void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
{
ARM_DRIVER_PPC *ppc_driver;
if (bank >= PPC_BANK_COUNT) {
return;
}
ppc_driver = ppc_bank_drivers[bank];
if (ppc_driver) {
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
ARM_PPC_PRIV_AND_NONPRIV);
}
}
void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
{
ARM_DRIVER_PPC *ppc_driver;
if (bank >= PPC_BANK_COUNT) {
return;
}
ppc_driver = ppc_bank_drivers[bank];
if (ppc_driver) {
ppc_driver->ConfigPeriph(pos, ARM_PPC_SECURE_ONLY,
ARM_PPC_PRIV_ONLY);
}
}
void ppc_clear_irq(void)
{
Driver_AHB_PPCEXP0.ClearInterrupt();
Driver_APB_PPC0.ClearInterrupt();
Driver_APB_PPC1.ClearInterrupt();
Driver_APB_PPCEXP0.ClearInterrupt();
Driver_APB_PPCEXP1.ClearInterrupt();
}
void mbed_psa_system_reset_impl(void)
{
__disable_irq();
mpc_revert_non_secure_to_secure_cfg();
NVIC->ICPR[0] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[1] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[2] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[3] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[4] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[5] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[6] = UINT32_MAX; /* Clear all pending interrupts */
NVIC->ICPR[7] = UINT32_MAX; /* Clear all pending interrupts */
NVIC_SystemReset();
}

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2018-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __TARGET_CFG_H__
#define __TARGET_CFG_H__
#include <stdint.h>
#include "tfm_peripherals_def.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Defines the word offsets of Slave Peripheral Protection Controller
* Registers
*/
enum ppc_bank_e
{
PPC_SP_DO_NOT_CONFIGURE = -1,
PPC_SP_AHB_PPC0 = 0,
PPC_SP_RES0,
PPC_SP_RES1,
PPC_SP_RES2,
PPC_SP_AHB_PPC_EXP0,
PPC_SP_AHB_PPC_EXP1,
PPC_SP_AHB_PPC_EXP2,
PPC_SP_AHB_PPC_EXP3,
PPC_SP_APB_PPC0,
PPC_SP_APB_PPC1,
PPC_SP_RES3,
PPC_SP_RES4,
PPC_SP_APB_PPC_EXP0,
PPC_SP_APB_PPC_EXP1,
PPC_SP_APB_PPC_EXP2,
PPC_SP_APB_PPC_EXP3,
};
/**
* \brief Store the addresses of memory regions
*/
struct memory_region_limits {
uint32_t non_secure_code_start;
uint32_t non_secure_partition_base;
uint32_t non_secure_partition_limit;
uint32_t veneer_base;
uint32_t veneer_limit;
uint32_t secondary_partition_base;
uint32_t secondary_partition_limit;
};
/**
* \brief Holds the data necessary to do isolation for a specific peripheral.
*/
struct tfm_spm_partition_platform_data_t
{
uint32_t periph_start;
uint32_t periph_limit;
int16_t periph_ppc_bank;
int16_t periph_ppc_loc;
};
/**
* \brief Configures the Memory Protection Controller.
*/
void mpc_init_cfg(void);
/**
* \brief Set to secure the initialized non-secure regions of
* the Memory Protection Controller.
*/
void mpc_revert_non_secure_to_secure_cfg(void);
/**
* \brief Configures the Peripheral Protection Controller.
*/
void ppc_init_cfg(void);
/**
* \brief Restict access to peripheral to secure
*/
void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc);
/**
* \brief Allow non-secure access to peripheral
*/
void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc);
/**
* \brief Enable secure unprivileged access to peripheral
*/
void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
/**
* \brief Clear secure unprivileged access to peripheral
*/
void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
/**
* \brief Clears PPC interrupt.
*/
void ppc_clear_irq(void);
/**
* \brief Configures SAU and IDAU.
*/
void sau_and_idau_cfg(void);
#ifdef __cplusplus
}
#endif
#endif /* __TARGET_CFG_H__ */

View File

@ -1,17 +0,0 @@
/*
* Copyright (c) 2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __TFM_PERIPHERALS_DEF_H__
#define __TFM_PERIPHERALS_DEF_H__
struct tfm_spm_partition_platform_data_t;
extern struct tfm_spm_partition_platform_data_t tfm_peripheral_std_uart;
#define TFM_PERIPHERAL_STD_UART (&tfm_peripheral_std_uart)
#endif /* __TFM_PERIPHERALS_DEF_H__ */

View File

@ -1,183 +0,0 @@
/*
* Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdbool.h>
#include "platform_description.h"
#include "target_cfg.h"
#include "device_definition.h"
#include "psa/client.h"
#include "tfm_secure_api.h"
#include "tfm_ioctl_api.h"
#include "platform_srv_impl.h"
#ifndef TFM_PSA_API
/*!
* \brief Verify access rights for memory addresses sent in io vectors
*
* \param[in] in_vec Pointer to in_vec array, which contains pointer
* to input arguments for the service
* \param[in] out_vec Pointer out_vec array, which contains pointer to
* output data of the pin service
*
* \return Returns true if memory is accessible by the service
*/
static bool memory_addr_check(const psa_invec *in_vec,
const psa_outvec *out_vec)
{
if ((in_vec->base != NULL) &&
(tfm_core_memory_permission_check((void *)in_vec->base, in_vec->len,
TFM_MEMORY_ACCESS_RO) == TFM_SUCCESS) &&
(out_vec->base != NULL) &&
(tfm_core_memory_permission_check((void *)out_vec->base, out_vec->len,
TFM_MEMORY_ACCESS_RW) == TFM_SUCCESS)) {
return true;
} else {
return false;
}
}
#endif /* TFM_PSA_API */
static enum tfm_platform_err_t
musca_b1_pin_service(const psa_invec *in_vec,
const psa_outvec *out_vec)
{
struct tfm_pin_service_args_t *args;
uint32_t *result;
enum gpio_altfunc_t altfunc;
enum pinmode_select_t pin_mode;
#ifndef TFM_PSA_API
if (memory_addr_check(in_vec, out_vec) == false) {
return TFM_PLATFORM_ERR_SYSTEM_ERROR;
}
#endif /* TFM_PSA_API */
if (in_vec->len != sizeof(struct tfm_pin_service_args_t) ||
out_vec->len != sizeof(uint32_t)) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args = (struct tfm_pin_service_args_t *)in_vec->base;
result = (uint32_t *)out_vec->base;
switch (args->type) {
case TFM_PIN_SERVICE_TYPE_SET_ALTFUNC:
altfunc = (enum gpio_altfunc_t)args->u.set_altfunc.alt_func;
*result = musca_b1_scc_set_alt_func(&MUSCA_B1_SCC_DEV_S, altfunc,
args->u.set_altfunc.pin_mask);
break;
case TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN:
altfunc = (enum gpio_altfunc_t)args->u.set_altfunc.alt_func;
*result = musca_b1_scc_set_default_in(&MUSCA_B1_SCC_DEV_S, altfunc,
args->u.set_default_in.pin_value,
args->u.set_default_in.default_in_value);
break;
case TFM_PIN_SERVICE_TYPE_SET_PIN_MODE:
pin_mode = (enum pinmode_select_t)args->u.set_pin_mode.pin_mode;
*result = musca_b1_scc_set_pinmode(&MUSCA_B1_SCC_DEV_S,
args->u.set_pin_mode.pin_mask,
pin_mode);
break;
default:
*result = SCC_INVALID_ARG;
break;
}
return TFM_PLATFORM_ERR_SUCCESS;
}
enum tfm_platform_err_t
tfm_platform_hal_gpio_service(const psa_invec *in_vec,
const psa_outvec *out_vec)
{
struct tfm_gpio_service_args_t *args;
struct tfm_gpio_service_out_t *out;
enum gpio_cmsdk_direction_t dir;
/* Alternate function is configured through the SCC, this is not used
* on Musca-B1, the default value is passed to the driver
*/
enum gpio_cmsdk_altfunc_t altfunc = GPIO_CMSDK_MAIN_FUNC;
#ifndef TFM_PSA_API
if (memory_addr_check(in_vec, out_vec) == false) {
return TFM_PLATFORM_ERR_SYSTEM_ERROR;
}
#endif /* TFM_PSA_API */
if (in_vec->len != sizeof(struct tfm_gpio_service_args_t) ||
out_vec->len != sizeof(struct tfm_gpio_service_out_t)) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args = (struct tfm_gpio_service_args_t *)in_vec->base;
out = (struct tfm_gpio_service_out_t *)out_vec->base;
switch (args->type) {
case TFM_GPIO_SERVICE_TYPE_INIT:
gpio_cmsdk_init(&GPIO0_CMSDK_DEV_S);
out->u.result = GPIO_CMSDK_ERR_NONE;
break;
case TFM_GPIO_SERVICE_TYPE_PIN_CONFIG:
dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
out->u.result = gpio_cmsdk_pin_config(
&GPIO0_CMSDK_DEV_S,
args->u.gpio_config.pin_num_or_mask,
dir, altfunc);
break;
case TFM_GPIO_SERVICE_TYPE_PIN_WRITE:
out->u.result = gpio_cmsdk_pin_write(
&GPIO0_CMSDK_DEV_S,
args->u.gpio_write.pin_num_or_mask,
args->u.gpio_write.value);
break;
case TFM_GPIO_SERVICE_TYPE_PIN_READ:
out->u.gpio_read_result.result =
gpio_cmsdk_pin_read(&GPIO0_CMSDK_DEV_S,
args->u.gpio_read.pin_num_or_mask,
&out->u.gpio_read_result.data);
break;
case TFM_GPIO_SERVICE_TYPE_PORT_CONFIG:
dir = (enum gpio_cmsdk_direction_t)args->u.gpio_config.direction;
out->u.result = gpio_cmsdk_port_config(
&GPIO0_CMSDK_DEV_S,
args->u.gpio_config.pin_num_or_mask,
dir, altfunc);
break;
case TFM_GPIO_SERVICE_TYPE_PORT_WRITE:
out->u.result = gpio_cmsdk_port_write(
&GPIO0_CMSDK_DEV_S,
args->u.gpio_write.pin_num_or_mask,
args->u.gpio_write.value);
break;
case TFM_GPIO_SERVICE_TYPE_PORT_READ:
out->u.gpio_read_result.result =
gpio_cmsdk_port_read(&GPIO0_CMSDK_DEV_S,
args->u.gpio_read.pin_num_or_mask,
&out->u.gpio_read_result.data);
break;
default:
out->u.result = GPIO_CMSDK_ERR_INVALID_ARG;
break;
}
in_vec++;
out_vec++;
return TFM_PLATFORM_ERR_SUCCESS;
}
enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request,
psa_invec *in_vec,
psa_outvec *out_vec)
{
switch (request) {
case TFM_PLATFORM_IOCTL_PIN_SERVICE:
return musca_b1_pin_service(in_vec, out_vec);
case TFM_PLATFORM_IOCTL_GPIO_SERVICE:
return tfm_platform_hal_gpio_service(in_vec, out_vec);
default:
return TFM_PLATFORM_ERR_NOT_SUPPORTED;
}
}

View File

@ -18,7 +18,7 @@
* limitations under the License.
*/
#include "../../../partition/region_defs.h"
#include "../../partition/region_defs.h"
#include "../cmsis_nvic.h"
#if !defined(MBED_ROM_START)

View File

@ -22,7 +22,7 @@
/* Linker script to configure memory regions. */
/* This file will be run trough the pre-processor. */
#include "../../../partition/region_defs.h"
#include "../../partition/region_defs.h"
#include "../cmsis_nvic.h"
/* Stack size is 1K for Mbed-OS */

View File

@ -24,7 +24,7 @@
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#include "../../partition/region_defs.h"
#include "../partition/region_defs.h"
#define NVIC_NUM_VECTORS (16 + 128)
/** Location of vectors to move in RAM */

View File

@ -29,52 +29,7 @@
* This is a default device configuration file with all peripherals enabled.
*/
#if defined(TARGET_MUSCA_B1_S)
/* ARM SCC */
#define MUSCA_B1_SCC_S
#define MUSCA_B1_SCC_DEV MUSCA_B1_SCC_DEV_S
/* ARM Memory Protection Controller (MPC) SIE 200 */
#define MPC_ISRAM0_S
#define MPC_ISRAM1_S
#define MPC_ISRAM2_S
#define MPC_ISRAM3_S
#define MPC_CODE_SRAM_S
#define MPC_CODE_SRAM_NS
#define MPC_QSPI_S
#define MPC_QSPI_NS
#define MPC_EFLASH0_S
#define MPC_EFLASH1_S
/* ARM Peripheral Protection Controllers (PPC) */
#define AHB_PPC0_S
#define AHB_PPCEXP0_S
#define AHB_PPCEXP1_S
#define AHB_PPCEXP2_S
#define AHB_PPCEXP3_S
#define APB_PPC0_S
#define APB_PPC1_S
#define APB_PPCEXP0_S
#define APB_PPCEXP1_S
#define APB_PPCEXP2_S
#define APB_PPCEXP3_S
/* Cadence QSPI Flash Controller */
#define QSPI_IP6514E_S
/* MT25QL Flash memory library */
#define MT25QL_S
/* GPIO */
#define GPIO0_CMSDK_S
#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S
#endif // defined(TARGET_MUSCA_B1_S)
#if defined(TARGET_MUSCA_B1_NS)
/*ARM UART Controller PL011*/
#define UART0_PL011_NS
@ -133,6 +88,5 @@
#define USEC_REPORTED_BITS (32 - USEC_REPORTED_SHIFT)
#define UART_DEFAULT_BAUD_RATE 9600U
#endif // TARGET_MUSCA_B1_NS
#endif /* __ARM_LTD_DEVICE_CFG_H__ */

Some files were not shown because too many files have changed in this diff Show More