Add ARM_MUSCA_B1 as a new target platform

Musca-B1 is a Cortex-M33 based target with security extension enabled.

- ARM_MUSCA_B1 is the non-secure target running mbed-os.
- ARM_MUSCA_B1_S is the secure target running TF-M.
- TF-M sources were imported and patched in previous commits.
- TF-M secure bootloader (McuBoot) for MUSCA_B1 is submitted by a
  pre-built binary.
- A post-build hook concatenates The secure and non-secure binaries,
  signs it and then concatenates the bootloader with the signed binary.

Change-Id: I4b36290941b5f0bb7aa7c12dda2f38b5c1e39ae2
Signed-off-by: Tamas Kaman <tamas.kaman@arm.com>
Signed-off-by: Gabor Abonyi <gabor.abonyi@arm.com>
pull/12458/head
Tamas Kaman 2020-01-08 21:08:12 +01:00 committed by Gabor Abonyi
parent a5b15a75be
commit 551c3c553c
97 changed files with 19064 additions and 6 deletions

View File

@ -43,6 +43,9 @@
},
"ARM_MUSCA_A1_S": {
"storage_type": "TDB_INTERNAL"
},
"ARM_MUSCA_B1_S": {
"storage_type": "TDB_INTERNAL"
}
}
}

View File

@ -27,6 +27,10 @@
"internal_size": "0x8000",
"internal_base_address": "0x00420000"
},
"ARM_MUSCA_B1_S": {
"internal_size": "0x8000",
"internal_base_address": "0x10000000"
},
"FVP_MPS2": {
"internal_size": "0x200000",
"internal_base_address": "0x00200000"

View File

@ -159,6 +159,12 @@
"ARM_MUSCA_A1_S": {
"stdio-baud-rate": 115200
},
"ARM_MUSCA_B1_NS": {
"stdio-baud-rate": 115200
},
"ARM_MUSCA_B1_S": {
"stdio-baud-rate": 115200
},
"EFM32": {
"stdio-baud-rate": 115200
},

View File

@ -1,4 +1,4 @@
Copyright 2019 Arm Limited and affiliates.
Copyright 2020 Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
Redistribution and use in source and binary forms, with or without

View File

@ -0,0 +1,2 @@
Unless specifically indicated otherwise in a file, MUSCA_B1 files in this directory are licensed under the BSD-3-Clause license,
as can be found in: LICENSE-bsd-3-clause.txt

View File

@ -0,0 +1,26 @@
Copyright 2019 Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,44 @@
/* mbed Microcontroller Library
* Copyright (c) 2019-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 MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
UART_0 = 0,
UART_1
} UARTName;
#define STDIO_UART_TX UART1_TX
#define STDIO_UART_RX UART1_RX
#define STDIO_UART UART_1
#define USBTX STDIO_UART_TX
#define USBRX STDIO_UART_RX
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,112 @@
/* 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.
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
typedef enum {
PA0 = 0,
PA1 = 1,
PA2 = 2,
PA3 = 3,
PA4 = 4,
PA5 = 5,
PA6 = 6,
PA7 = 7,
PA8 = 8,
PA9 = 9,
PA10 = 10,
PA11 = 11,
PA12 = 12,
PA13 = 13,
PA14 = 14,
PA15 = 15,
PA16 = 16,
PA17 = 17,
PA18 = 18,
PA19 = 19,
PA20 = 20,
PA21 = 21,
PA22 = 22,
PA23 = 23,
PA24 = 24,
PA25 = 25,
/* Arduino Connector Namings */
D0 = PA0,
D1 = PA1,
D2 = PA2,
D3 = PA3,
D4 = PA4,
D5 = PA5,
D6 = PA6,
D7 = PA7,
D8 = PA8,
D9 = PA9,
D10 = PA10,
D11 = PA11,
D12 = PA12,
D13 = PA13,
D14 = PA14,
D15 = PA15,
/* UART pins */
UART0_RX = PA0, /* Alternate Function - 1 */
UART0_TX = PA1, /* Alternate Function - 1 */
UART1_RX = PA16,
UART1_TX = PA17,
LED1 = PA2,
LED2 = PA3,
LED3 = PA4,
/* Not connected */
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PRIMARY_FUNC = 0,
ALTERNATE_FUNC_1 = 1,
ALTERNATE_FUNC_2 = 2,
ALTERNATE_FUNC_3 = 3
} PinFunction;
typedef enum {
PullNone = 0,
PullUp,
PullDown,
PullDefault = PullNone
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,64 @@
#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
/*
* Copyright (c) 2019-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"
#include "../cmsis_nvic.h"
#if !defined(MBED_ROM_START)
#define MBED_ROM_START NS_CODE_START // 0x0A060400
#endif
#if !defined(MBED_ROM_SIZE)
#define MBED_ROM_SIZE NS_CODE_SIZE // 0x7f800
#endif
#if !defined(MBED_RAM_START)
#define MBED_RAM_START NS_DATA_START // 0x20040000
#endif
#if !defined(MBED_RAM_SIZE)
#define MBED_RAM_SIZE NS_DATA_SIZE // 0x40000
#endif
#define VECTOR_SIZE NVIC_RAM_VECTOR_SIZE
#if !defined(MBED_BOOT_STACK_SIZE)
#define MBED_BOOT_STACK_SIZE 0x400
#endif
#define RAM_FIXED_SIZE (MBED_BOOT_STACK_SIZE+VECTOR_SIZE)
LR_CODE MBED_ROM_START MBED_ROM_SIZE {
ER_CODE MBED_ROM_START MBED_ROM_SIZE {
*.o (VECTOR +First)
.ANY (+RO)
}
RW_IRAM1 (MBED_RAM_START+VECTOR_SIZE) (MBED_RAM_SIZE-VECTOR_SIZE) {
* (+RW) ; RW data that gets copied from Flash to SRAM
* (+ZI) ; ZI data that gets initialised to zero in SRAM
}
ARM_LIB_HEAP AlignExpr(+0, 16) EMPTY (MBED_RAM_SIZE-RAM_FIXED_SIZE+MBED_RAM_START-AlignExpr(ImageLimit(RW_IRAM1), 16)) {
}
ARM_LIB_STACK (MBED_RAM_START+MBED_RAM_SIZE) EMPTY -MBED_BOOT_STACK_SIZE { ; stack
}
}

View File

@ -0,0 +1,275 @@
;/*
; * Copyright (c) 2019-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 >>> ------------------
;*/
; Vector Table Mapped to Address 0 at Reset
AREA VECTOR, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit|
__Vectors ;Core Interrupts
DCD |Image$$ARM_LIB_STACK$$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 0 ; Reserved
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 0 ; 9: Reserved
DCD 0 ; 10: Reserved
DCD 0 ; 11: Reserved
DCD 0 ; 12: Reserved
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 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 0 ; 95: Reserved
DCD 0 ; 96: Reserved
DCD 0 ; 97:127 Reserved
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
; Reset Handler
AREA RESET, CODE, READONLY
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX 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 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 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 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
ALIGN
END

View File

@ -0,0 +1,212 @@
;/*
; * Copyright (c) 2019-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
; */
/* Linker script to configure memory regions. */
/* This file will be run trough the pre-processor. */
#include "../../../partition/region_defs.h"
#include "../cmsis_nvic.h"
/* Stack size is 1K for Mbed-OS */
#if !defined(MBED_BOOT_STACK_SIZE)
#define MBED_BOOT_STACK_SIZE 0x400
#endif
MEMORY
{
CODE_RAM (rx) : ORIGIN = NS_CODE_START, LENGTH = ((TOTAL_CODE_SRAM_SIZE / 2) - BL2_HEADER_SIZE)
/* Vector table is copied to RAM, so RAM address needs to be adjusted */
RAM (rwx) : ORIGIN = NVIC_RAM_VECTOR_LIMIT, LENGTH = (NS_DATA_SIZE - NVIC_RAM_VECTOR_SIZE)
}
__stack_size__ = MBED_BOOT_STACK_SIZE;
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
ENTRY(Reset_Handler)
SECTIONS
{
/* Startup section is loaded to Flash and runs from Flash */
.startup :
{
KEEP(*(.vectors))
__Vectors_End = .;
__Vectors_Size = __Vectors_End - __Vectors;
__end__ = .;
KEEP(*(.init))
KEEP(*(.fini))
} > CODE_RAM
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > CODE_RAM
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > CODE_RAM
__exidx_end = .;
/* The text section is loaded into Flash but runs from SRAM
* The load address is aligned to 8 bytes
*/
.text : ALIGN(8)
{
*(.text*)
/* .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*))
} >CODE_RAM
. = ALIGN(8); /* This alignment is needed to make the section size 8 bytes aligned */
/* Create same symbols that armclang does so that in the c files
* we do not have to deal with the compiler type
*/
Image$$ER_CODE_SRAM$$Base = ADDR(.text);
Image$$ER_CODE_SRAM$$Limit = .;
Image$$ER_CODE_SRAM$$Length = Image$$ER_CODE_SRAM$$Limit - Image$$ER_CODE_SRAM$$Base;
Load$$ER_CODE_SRAM$$Base = LOADADDR(.text);
Load$$ER_CODE_SRAM$$Length = Image$$ER_CODE_SRAM$$Length;
Load$$ER_CODE_SRAM$$Limit = Load$$ER_CODE_SRAM$$Base + Load$$ER_CODE_SRAM$$Length;
/* To copy multiple ROM to RAM sections,
* define etext2/data2_start/data2_end and
* define __STARTUP_COPY_MULTIPLE in startup_cmsdk_musca_ns.S */
.copy.table :
{
. = ALIGN(8);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG (__data_end__ - __data_start__)
LONG (DEFINED(__etext2) ? __etext2 : 0)
LONG (DEFINED(__data2_start__) ? __data2_start__ : 0)
LONG (DEFINED(__data2_start__) ? __data2_end__ - __data2_start__ : 0)
__copy_table_end__ = .;
} > CODE_RAM
/* To clear multiple BSS sections,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_cmsdk_musca_ns.S */
.zero.table :
{
. = ALIGN(8);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
LONG (DEFINED(__bss2_start__) ? __bss2_start__ : 0)
LONG (DEFINED(__bss2_start__) ? __bss2_end__ - __bss2_start__ : 0)
__zero_table_end__ = .;
} > CODE_RAM
__etext = .;
.data : ALIGN(8)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(8);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(8);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(8);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(8);
/* All data end */
__data_end__ = .;
} > RAM AT>CODE_RAM
.bss :
{
. = ALIGN(8);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(8);
__bss_end__ = .;
} > RAM
bss_size = __bss_end__ - __bss_start__;
.stack :
{
. = ALIGN(8);
__StackLimit = .;
KEEP(*(.stack*))
. += __stack_size__;
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);
.heap (COPY):
{
. = ALIGN(8);
__HeapBase = .;
__end__ = .;
end = __end__;
KEEP(*(.heap*))
. += (ORIGIN(RAM) + LENGTH(RAM) - .);
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > RAM
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackTop <= (NS_DATA_START + NS_DATA_SIZE), "RAM region overflowed")
}

View File

@ -0,0 +1,392 @@
;/*
; * Copyright (c) 2019-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 __StackTop /* 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 0 /* Reserved */
.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 0 /* 9: Reserved */
.long 0 /* 10: Reserved */
.long 0 /* 11: Reserved */
.long 0 /* 12: Reserved */
.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 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 GpTimer1_IRQHandler /* 72: General Purpose Timer0 */
.long GpTimer0_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 */
#ifndef __NO_SYSTEM_INIT
bl SystemInit
#endif
#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 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 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 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

@ -0,0 +1,35 @@
/* 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.
*/
/*
* This file is included from the linker script,
* limited set of C constructs can be used here
*/
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#include "../../partition/region_defs.h"
#define NVIC_NUM_VECTORS (16 + 128)
/** Location of vectors to move in RAM */
#define NVIC_RAM_VECTOR_ADDRESS NS_DATA_START
#define NVIC_RAM_VECTOR_SIZE (NVIC_NUM_VECTORS * 4)
#define NVIC_RAM_VECTOR_LIMIT (NVIC_RAM_VECTOR_ADDRESS + NVIC_RAM_VECTOR_SIZE)
#endif

View File

@ -0,0 +1,25 @@
/*
* 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 "cmsis_nvic_virtual.h"
#include "psa/lifecycle.h"
void NVIC_SystemReset(void)
{
mbed_psa_system_reset();
}

View File

@ -0,0 +1,52 @@
/*
* 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 "cmsis.h"
#ifndef NVIC_VIRTUAL_H
#define NVIC_VIRTUAL_H
#ifdef __cplusplus
extern "C" {
#endif
/* NVIC functions */
#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
#define NVIC_EnableIRQ __NVIC_EnableIRQ
#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
#define NVIC_DisableIRQ __NVIC_DisableIRQ
#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
#define NVIC_GetActive __NVIC_GetActive
#define NVIC_SetPriority __NVIC_SetPriority
#define NVIC_GetPriority __NVIC_GetPriority
/**
* \brief Overriding the default CMSIS system reset implementation by calling
* secure TFM service.
*
*/
void NVIC_SystemReset(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,168 @@
/*
* 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 timer_gp_drv.c
*
* \brief Generic driver for general purpose timer.
*/
#include "timer_gp_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))))
/**
* \brief Timer register map structure
*
*/
struct timer_gp_reg_map_t {
volatile uint32_t reset; /*!< Offset: 0x000 (R/W) Control Reset */
volatile uint32_t irq_mask; /*!< Offset: 0x004 (R/W) Masked Interrupt */
volatile uint32_t irq_clear; /*!< Offset: 0x008 (R/W) Interrupt Clear */
volatile uint32_t reserved; /*!< Offset: 0x00C Reserved */
volatile uint32_t alarm0; /*!< Offset: 0x010 (R/W) Alarm0 data value */
volatile uint32_t alarm1; /*!< Offset: 0x014 (R/W) Alarm1 data value */
volatile uint32_t irq_status; /*!< Offset: 0x018 (R) Raw Interrupt status */
volatile uint32_t counter; /*!< Offset: 0x01C (R) Counter data value */
};
/**
* \brief Reset control register bit identifiers
*
*/
enum reset_reg_bits_t{
RESET_REG_INDEX = 0
/* 1-31: Reserved. Read as zero. Do No Modify (DNM). */
};
void timer_gp_init(const struct timer_gp_dev_t* dev)
{
if (dev->data->is_initialized == false) {
timer_gp_interrupt_disable(dev, TIMER_GP_ALARM_0);
timer_gp_interrupt_clear(dev, TIMER_GP_ALARM_0);
timer_gp_interrupt_disable(dev, TIMER_GP_ALARM_1);
timer_gp_interrupt_clear(dev, TIMER_GP_ALARM_1);
timer_gp_set_alarm_value(dev, TIMER_GP_ALARM_0, dev->data->alarm0_init);
timer_gp_set_alarm_value(dev, TIMER_GP_ALARM_1, dev->data->alarm1_init);
timer_gp_counter_reset(dev);
dev->data->is_initialized = true;
}
}
void timer_gp_counter_reset(const struct timer_gp_dev_t* dev)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->reset, RESET_REG_INDEX);
/* Reset bit is not self-clearing and some pulse width is required
* for successful reset, so we have to check whether the
* timer counter is set to reset value. Until this bit is asserted
* the timer won't be started.
* The timer is running only if the reset bit is cleared.*/
while (timer_gp_get_counter(dev) != TIMER_GP_DEFAULT_RESET)
;
CLR_BIT(register_map->reset, RESET_REG_INDEX);
}
uint32_t timer_gp_get_counter(const struct timer_gp_dev_t* dev)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
return register_map->counter;
}
void timer_gp_interrupt_enable(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->irq_mask, alarm);
}
void timer_gp_interrupt_disable(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->irq_mask, alarm);
}
bool timer_gp_interrupt_is_enabled(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->irq_mask, alarm);
}
bool timer_gp_interrupt_is_active(const struct timer_gp_dev_t* dev,
const enum timer_gp_read_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->irq_status, alarm);
}
void timer_gp_interrupt_clear(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
enum timer_gp_read_alarm_identifier_t read_alarm =
((alarm == TIMER_GP_ALARM_0) ?
(TIMER_GP_READ_ALARM_0) :
(TIMER_GP_READ_ALARM_1));
SET_BIT(register_map->irq_clear, alarm);
/* Clear bit is not self-clearing and some pulse width is required
* for successful interrupt clear, so we have to check whether the
* interrupt is cleared. */
while(timer_gp_interrupt_is_active(dev, read_alarm))
;
CLR_BIT(register_map->irq_clear, alarm);
}
void timer_gp_set_alarm_value(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm,
const uint32_t value)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
if (alarm == TIMER_GP_ALARM_0) {
register_map->alarm0 = value;
} else {
register_map->alarm1 = value;
}
}
uint32_t timer_gp_get_alarm_value(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm)
{
struct timer_gp_reg_map_t* const register_map =
(struct timer_gp_reg_map_t*)dev->cfg->base;
if (alarm == TIMER_GP_ALARM_0) {
return register_map->alarm0;
} else {
return register_map->alarm1;
}
}

View File

@ -0,0 +1,201 @@
/*
* 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 timer_gp_drv.h
*
* \brief Generic driver for general purpose timer.
*
* \details
* The free running counter is a 32 bit size counter that counts
* up to 0xFFFFFFFF.
* At this maximum value it wraps around to 0x00000000 and continues
* incrementing.
* Software can reset the counter to default 1 by calling
* \ref timer_gp_counter_reset.
* The counter implements two compare interrupts. When the counter
* reaches compare value "alarm0" or "alarm1" value it can trigger a
* corresponding interrupt.
*/
#ifndef __TIMER_GP_DRV_H__
#define __TIMER_GP_DRV_H__
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TIMER_GP_MAX_VALUE UINT32_MAX /*!< max of 32-bit */
#define TIMER_GP_DEFAULT_RESET 1U
/*!< Counter's reset value will be set at HW level if reset bit is asserted */
/** GP timer device structure */
struct timer_gp_dev_cfg_t {
const uintptr_t base; /*!< Timer base address */
};
/** GP timer device data structure */
struct timer_gp_dev_data_t {
bool is_initialized;
uint32_t alarm0_init; /*!< Alarm0 value will be set by init */
uint32_t alarm1_init; /*!< Alarm1 value will be set by init */
};
/** GP timer device structure */
struct timer_gp_dev_t {
const struct timer_gp_dev_cfg_t* const cfg; /*!< Timer configuration */
struct timer_gp_dev_data_t* const data; /*!< Timer data */
};
/**
* \brief GP Timer alarm number identifiers
*
*/
enum timer_gp_alarm_identifier_t{
TIMER_GP_ALARM_0 = 0,
TIMER_GP_ALARM_1 = 1
};
/**
* \brief GP Timer read alarm number identifiers
*
*/
enum timer_gp_read_alarm_identifier_t{
TIMER_GP_READ_ALARM_0 = 0,
TIMER_GP_READ_ALARM_1 = 1,
TIMER_GP_READ_ALARM_COMBINED = 2
/*!< Combined is asserted if Alarm1 OR Alarm2 is asserted */
};
/**
* \brief Initializes timer to a known default state, which is:
* - interrupts disabled
* - alarm0 and alarm1 set to init value in \ref timer_gp_dev_data_t
* - timer reset to default reset value \ref TIMER_GP_DEFAULT_RESET
* Init should be called prior to any other process and
* it's the caller's responsibility to follow proper call order.
* More than one call results fall through.
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
*/
void timer_gp_init(const struct timer_gp_dev_t* dev);
/**
* \brief Resets the timer counter to 1.
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
*/
void timer_gp_counter_reset(const struct timer_gp_dev_t* dev);
/**
* \brief Read the 32bit free runnning counter's current value
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
*
* \return 32bit counter current value
*/
uint32_t timer_gp_get_counter(const struct timer_gp_dev_t* dev);
/**
* \brief Enable alarm interrupt of the given source
* Note: This function is not interrupt safe.
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source of the interrupt
* \ref timer_gp_alarm_identifier_t
*
*/
void timer_gp_interrupt_enable(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm);
/**
* \brief Disable alarm interrupt of the given source
* Note: This function is not interrupt safe.
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source of the interrupt
* \ref timer_gp_alarm_identifier_t
*
*/
void timer_gp_interrupt_disable(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm);
/**
* \brief Get alarm interrupt enabled status of the given source
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source of the interrupt
* \ref timer_gp_alarm_identifier_t
*
* \return true if enabled, false if not
*/
bool timer_gp_interrupt_is_enabled(const struct timer_gp_dev_t* dev,
const enum
timer_gp_alarm_identifier_t alarm);
/**
* \brief Get alarm interrupt pending status of the given source
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source of the interrupt
* \ref timer_gp_read_alarm_identifier_t
*
* \return true if active, false if not
*/
bool timer_gp_interrupt_is_active(const struct timer_gp_dev_t* dev,
const enum timer_gp_read_alarm_identifier_t alarm);
/**
* \brief Clear alarm interrupt of the given source
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source of the interrupt
* \ref timer_gp_alarm_identifier_t
*
*/
void timer_gp_interrupt_clear(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm);
/**
* \brief Set alarm value of the given source
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source \ref timer_gp_alarm_identifier_t
* \param[in] value When the counter reaches this tick value
* corresponding interrupt status will be asserted.
*/
void timer_gp_set_alarm_value(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm,
const uint32_t value);
/**
* \brief Get alarm value of the given source
*
* \param[in] dev Timer device struct \ref timer_gp_dev_t
* \param[in] alarm Alarm source \ref timer_gp_alarm_identifier_t
*
* \return value Counter value when the alarm is asserted.
*/
uint32_t timer_gp_get_alarm_value(const struct timer_gp_dev_t* dev,
const enum timer_gp_alarm_identifier_t alarm);
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_GP_DRV_H__ */

View File

@ -0,0 +1,852 @@
/*
* 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.
*/
/**
* \file uart_pl011_drv.h
* \brief Driver for ARM UART PL011.
*/
#ifndef __UART_PL011_DRV_H__
#define __UART_PL011_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief ARM UART PL011 state types
*/
enum uart_pl011_state_t {
UART_PL011_UNINITIALIZED = 0x0u,
UART_PL011_INITIALIZED = 0x1u,
};
#define UART_PL011_UARTRSR_FE_ERR_OFF 0x0u
/*!< Receive Status Register Frame Error bit field offset */
#define UART_PL011_UARTRSR_PE_ERR_OFF 0x1u
/*!< Receive Status Register Parity Error bit field offset */
#define UART_PL011_UARTRSR_BE_ERR_OFF 0x2u
/*!< Receive Status Register Break Error bit field offset */
#define UART_PL011_UARTRSR_OE_ERR_OFF 0x3u
/*!< Receive Status Register Overrun Error bit field offset */
#define UART_PL011_RX_ERR_MASK ( \
0x1u<<UART_PL011_UARTRSR_FE_ERR_OFF \
| 0x1u<<UART_PL011_UARTRSR_PE_ERR_OFF \
| 0x1u<<UART_PL011_UARTRSR_BE_ERR_OFF \
| 0x1u<<UART_PL011_UARTRSR_OE_ERR_OFF)
/*!< Receive Status Register Error Mask */
#define UART_PL011_UARTFR_CTS_OFF 0x0u
/*!< Flag Register Clear to send bit field offset */
#define UART_PL011_UARTFR_DSR_OFF 0x1u
/*!< Flag Register Data set ready bit field offset */
#define UART_PL011_UARTFR_DCD_OFF 0x2u
/*!< Flag Register Data carrier detect bit field offset */
#define UART_PL011_UARTFR_BUSYBIT_OFF 0x3u
/*!< Flag Register Busy bit field offset */
#define UART_PL011_UARTFR_RX_FIFO_EMPTY_OFF 0x4u
/*!< Flag Register Receive fifo empty bit field offset */
#define UART_PL011_UARTFR_TX_FIFO_FULL_OFF 0x5u
/*!< Flag Register Transmit fifo full bit field offset */
#define UART_PL011_UARTFR_RX_FIFO_FULL_OFF 0x6u
/*!< Flag Register Receive fifo full bit field offset */
#define UART_PL011_UARTFR_TX_FIFO_EMPTY_OFF 0x7u
/*!< Flag Register Transmit fifo empty bit field offset */
#define UART_PL011_UARTFR_RI_OFF 0x8u
/*!< Flag Register Ring indicator bit field offset */
#define UART_PL011_UARTLCR_H_BRK_OFF 0x0u
/*!< Line Control Register Break bit field offset */
#define UART_PL011_UARTLCR_H_PEN_OFF 0x1u
/*!< Line Control Register Parity enable bit field offset */
#define UART_PL011_UARTLCR_H_EPS_OFF 0x2u
/*!< Line Control Register Even parity select bit field offset */
#define UART_PL011_UARTLCR_H_STP2_OFF 0x3u
/*!< Line Control Register 2 stop bit select bit field offset */
#define UART_PL011_UARTLCR_H_FEN_OFF 0x4u
/*!< Line Control Register Fifo enable bit field offset */
#define UART_PL011_UARTLCR_H_WLEN_OFF 0x5u
/*!< Line Control Register Word length bit field offset */
#define UART_PL011_UARTLCR_H_SPS_OFF 0x7u
/*!< Line Control Register Stick parity select bit field offset */
/**
* \brief Allowed word length options UART PL011
*/
enum uart_pl011_wlen_t {
UART_PL011_WLEN_5 = (0x0u<<UART_PL011_UARTLCR_H_WLEN_OFF),
UART_PL011_WLEN_6 = (0x1u<<UART_PL011_UARTLCR_H_WLEN_OFF),
UART_PL011_WLEN_7 = (0x2u<<UART_PL011_UARTLCR_H_WLEN_OFF),
UART_PL011_WLEN_8 = (0x3u<<UART_PL011_UARTLCR_H_WLEN_OFF),
};
/**
* \brief Allowed parity options UART PL011
*/
enum uart_pl011_parity_t {
UART_PL011_PARITY_DISABLED = (0x0u<<UART_PL011_UARTLCR_H_PEN_OFF),
UART_PL011_PARITY_ODD = (0x1u<<UART_PL011_UARTLCR_H_PEN_OFF
| 0x0u<<UART_PL011_UARTLCR_H_EPS_OFF
| 0x0u<<UART_PL011_UARTLCR_H_SPS_OFF),
UART_PL011_PARITY_EVEN = (0x1u<<UART_PL011_UARTLCR_H_PEN_OFF
| 0x1u<<UART_PL011_UARTLCR_H_EPS_OFF
| 0x0u<<UART_PL011_UARTLCR_H_SPS_OFF),
UART_PL011_PARITY_STICKY_ONE= (0x1u<<UART_PL011_UARTLCR_H_PEN_OFF
| 0x0u<<UART_PL011_UARTLCR_H_EPS_OFF
| 0x1u<<UART_PL011_UARTLCR_H_SPS_OFF),
UART_PL011_PARITY_STICKY_ZERO= (0x1u<<UART_PL011_UARTLCR_H_PEN_OFF
| 0x1u<<UART_PL011_UARTLCR_H_EPS_OFF
| 0x1u<<UART_PL011_UARTLCR_H_SPS_OFF),
};
/**
* \brief Allowed stop bits options UART PL011
*/
enum uart_pl011_stopbit_t {
UART_PL011_STOPBIT_1 = (0x0u<<UART_PL011_UARTLCR_H_STP2_OFF),
UART_PL011_STOPBIT_2 = (0x1u<<UART_PL011_UARTLCR_H_STP2_OFF),
};
#define UART_PL011_UARTCR_UARTEN_OFF 0x0u
/*!< Control Register Uart enable bit field offset */
#define UART_PL011_UARTCR_SIREN_OFF 0x1u
/*!< Control Register Sir enable bit field offset */
#define UART_PL011_UARTCR_SIRLP_OFF 0x2u
/*!< Control Register Sir low power bit field offset */
#define UART_PL011_UARTCR_LBE_OFF 0x7u
/*!< Control Register Loop back enable bit field offset */
#define UART_PL011_UARTCR_TXE_OFF 0x8u
/*!< Control Register Transmit enable bit field offset */
#define UART_PL011_UARTCR_RXE_OFF 0x9u
/*!< Control Register Receive enable bit field offset */
#define UART_PL011_UARTCR_DTR_OFF 0xAu
/*!< Control Register Data transmit ready bit field offset */
#define UART_PL011_UARTCR_RTS_OFF 0xBu
/*!< Control Register Request to send bit field offset */
#define UART_PL011_UARTCR_OUT1_OFF 0xCu
/*!< Control Register Out1 bit field offset */
#define UART_PL011_UARTCR_OUT2_OFF 0xDu
/*!< Control Register Out2 bit field offset */
#define UART_PL011_UARTCR_RTSE_OFF 0xEu
/*!< Control Register RTS hardware flow control enable bit field offset */
#define UART_PL011_UARTCR_CTSE_OFF 0xFu
/*!< Control Register CTS hardware flow control enable bit field offset */
#define UART_PL011_UARTIFLS_TX_OFF 0x0u
/*!< Interrupt FIFO Level Select Register Transmit bit field offset */
#define UART_PL011_UARTIFLS_RX_OFF 0x3u
/*!< Interrupt FIFO Level Select Register Receive bit field offset */
/**
* \brief UART Receive fifo levels
*/
enum uart_pl011_rx_fifo_lvl_t {
UART_PL011_RX_FIFO_LVL_1_8 = (0x0u<<UART_PL011_UARTIFLS_RX_OFF),
UART_PL011_RX_FIFO_LVL_1_4 = (0x1u<<UART_PL011_UARTIFLS_RX_OFF),
UART_PL011_RX_FIFO_LVL_1_2 = (0x2u<<UART_PL011_UARTIFLS_RX_OFF),
UART_PL011_RX_FIFO_LVL_3_4 = (0x3u<<UART_PL011_UARTIFLS_RX_OFF),
UART_PL011_RX_FIFO_LVL_7_8 = (0x4u<<UART_PL011_UARTIFLS_RX_OFF),
};
/**
* \brief UART Transmit fifo levels
*/
enum uart_pl011_tx_fifo_lvl_t {
UART_PL011_TX_FIFO_LVL_1_8 = (0x0u<<UART_PL011_UARTIFLS_TX_OFF),
UART_PL011_TX_FIFO_LVL_1_4 = (0x1u<<UART_PL011_UARTIFLS_TX_OFF),
UART_PL011_TX_FIFO_LVL_1_2 = (0x2u<<UART_PL011_UARTIFLS_TX_OFF),
UART_PL011_TX_FIFO_LVL_3_4 = (0x3u<<UART_PL011_UARTIFLS_TX_OFF),
UART_PL011_TX_FIFO_LVL_7_8 = (0x4u<<UART_PL011_UARTIFLS_TX_OFF),
};
#define UART_PL011_UARTDMACR_RXEN_OFF 0x0u
/*!< DMA Control Register Receive DMA enable bit field offset */
#define UART_PL011_UARTDMACR_TXEN_OFF 0x1u
/*!< DMA Control Register Transmit DMA enable bit field offset */
#define UART_PL011_UARTDMACR_ON_ERR_OFF 0x2u
/*!< DMA Control Register DMA on error bit field offset */
/**
* \brief Transmit DMA Enable
*/
enum uart_pl011_tx_dma_t {
UART_PL011_TX_DMA_DISABLE = (0x0u<<UART_PL011_UARTDMACR_TXEN_OFF),
UART_PL011_TX_DMA_ENABLE = (0x1u<<UART_PL011_UARTDMACR_TXEN_OFF),
};
/**
* \brief Receive DMA Enable
*/
enum uart_pl011_rx_dma_t {
UART_PL011_RX_DMA_DISABLE = (0x0u<<UART_PL011_UARTDMACR_RXEN_OFF),
UART_PL011_RX_DMA_ENABLE = (0x1u<<UART_PL011_UARTDMACR_RXEN_OFF),
UART_PL011_RX_DMA_ON_ERR_EN= (0x1u<<UART_PL011_UARTDMACR_RXEN_OFF
| 0x1u<<UART_PL011_UARTDMACR_ON_ERR_OFF),
};
#define UART_PL011_INTR_RI_OFF 0x0u
/*!< Ring indicator interrupt bit field offset */
#define UART_PL011_INTR_CTS_OFF 0x1u
/*!< Clear to send interrupt bit field offset */
#define UART_PL011_INTR_DCD_OFF 0x2u
/*!< Data carrier detect interrupt bit field offset */
#define UART_PL011_INTR_DSR_OFF 0x3u
/*!< Data set ready interrupt bit field offset */
#define UART_PL011_INTR_RX_OFF 0x4u
/*!< Receive interrupt bit field offset */
#define UART_PL011_INTR_TX_OFF 0x5u
/*!< Transmit interrupt bit field offset */
#define UART_PL011_INTR_RT_OFF 0x6u
/*!< Receive timeout interrupt bit field offset */
#define UART_PL011_INTR_FE_OFF 0x7u
/*!< Frame error interrupt bit field offset */
#define UART_PL011_INTR_PE_OFF 0x8u
/*!< Parity error interrupt bit field offset */
#define UART_PL011_INTR_BE_OFF 0x9u
/*!< Break error interrupt bit field offset */
#define UART_PL011_INTR_OE_OFF 0xAu
/*!< Overrun error interrupt bit field offset */
/**
* \brief ARM UART PL011 Interrupt data structure
*/
enum uart_pl011_intr_t {
UART_PL011_RI_INTR_MASK = (0x1u<<UART_PL011_INTR_RI_OFF),
UART_PL011_CTS_INTR_MASK = (0x1u<<UART_PL011_INTR_CTS_OFF),
UART_PL011_DCD_INTR_MASK = (0x1u<<UART_PL011_INTR_DCD_OFF),
UART_PL011_DSR_INTR_MASK = (0x1u<<UART_PL011_INTR_DSR_OFF),
UART_PL011_RX_INTR_MASK = (0x1u<<UART_PL011_INTR_RX_OFF),
UART_PL011_TX_INTR_MASK = (0x1u<<UART_PL011_INTR_TX_OFF),
UART_PL011_RT_INTR_MASK = (0x1u<<UART_PL011_INTR_RT_OFF),
UART_PL011_FE_INTR_MASK = (0x1u<<UART_PL011_INTR_FE_OFF),
UART_PL011_PE_INTR_MASK = (0x1u<<UART_PL011_INTR_PE_OFF),
UART_PL011_BE_INTR_MASK = (0x1u<<UART_PL011_INTR_BE_OFF),
UART_PL011_OE_INTR_MASK = (0x1u<<UART_PL011_INTR_OE_OFF),
};
/**
* \brief ARM UART PL011 error enumeration types
*/
enum uart_pl011_error_t {
UART_PL011_ERR_NONE = (0x0u),
UART_PL011_ERR_RX_FRAME = (0x1u<<UART_PL011_UARTRSR_FE_ERR_OFF),
UART_PL011_ERR_RX_PARITY = (0x1u<<UART_PL011_UARTRSR_PE_ERR_OFF),
UART_PL011_ERR_RX_BREAK = (0x1u<<UART_PL011_UARTRSR_BE_ERR_OFF),
UART_PL011_ERR_RX_OVERFLOW = (0x1u<<UART_PL011_UARTRSR_OE_ERR_OFF),
UART_PL011_ERR_INVALID_ARG = (UART_PL011_RX_ERR_MASK + 1),
UART_PL011_ERR_NOT_READY,
UART_PL011_ERR_INVALID_BAUD,
UART_PL011_ERR_NOT_INIT,
};
/**
* \brief ARM UART PL011 device configuration structure
*/
struct uart_pl011_dev_cfg_t {
const uint32_t base; /*!< UART PL011 base address */
const uint32_t def_baudrate; /*!< Default baudrate */
const enum uart_pl011_wlen_t def_wlen; /*!< Default word length */
const enum uart_pl011_parity_t def_parity; /*!< Default parity */
const enum uart_pl011_stopbit_t def_stopbit; /*!< Default stop bits */
};
/**
* \brief ARM UART PL011 device data structure
*/
struct uart_pl011_dev_data_t {
enum uart_pl011_state_t state; /*!< UART State */
uint32_t uart_clk; /*!< UART clock */
uint32_t baudrate; /*!< Baudrate */
};
/**
* \brief ARM UART PL011 device structure
*/
struct uart_pl011_dev_t {
const struct uart_pl011_dev_cfg_t* const cfg;
/*!< UART PL011 configuration */
struct uart_pl011_dev_data_t* const data;
/*!< UART PL011 data */
};
/**
* \brief Initializes UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
* \param[in] uart_clk UART clock used by the device.
*
* It uses the default baudrate to configure UART.
*
* \return Returns error code as specified in \ref uart_pl011_error_t
*
* \note This API should be called before calling any of the below UART APIs.
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_error_t uart_pl011_init(struct uart_pl011_dev_t* dev,
uint32_t uart_clk);
/**
* \brief Uninitializes UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_uninit(struct uart_pl011_dev_t* dev);
/**
* \brief Returns the UART PL011 operational state.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \return Returns the UART operational state
*
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_state_t uart_pl011_get_state(struct uart_pl011_dev_t* dev);
/**
* \brief Sets the UART baudrate.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] baudrate New baudrate.
*
* \return Returns error code as specified in \ref uart_pl011_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_error_t uart_pl011_set_baudrate(
struct uart_pl011_dev_t* dev, uint32_t baudrate);
/**
* \brief Gets the UART baudrate.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Returns the UART baudrate.
*
* \note The UART should be in valid state before calling this API
* \ref uart_pl011_get_state should return UART_PL011_INITIALIZED
* \note This function doesn't check if dev is NULL.
*/
uint32_t uart_pl011_get_baudrate(struct uart_pl011_dev_t* dev);
/**
* \brief Enables UART interrupts
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] mask Bit mask for enabling/disabling interrupts
* \ref uart_pl011_intr_t
*
* \note User is responsible to configure the interrupt vector and
* the interrupt controller.
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_intr(struct uart_pl011_dev_t* dev,
enum uart_pl011_intr_t mask);
/**
* \brief Disables UART interrupts
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] mask Bit mask for enabling/disabling interrupts
* \ref uart_pl011_intr_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_intr(struct uart_pl011_dev_t* dev,
enum uart_pl011_intr_t mask);
/**
* \brief Clears UART Interrupt
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] mask Bit mask for clearing interrupts \ref uart_pl011_intr_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_clear_intr(struct uart_pl011_dev_t* dev,
enum uart_pl011_intr_t mask);
/**
* \brief Returns the UART Masked interrupt status
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Masked interrupt status \ref uart_pl011_intr_t
*
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_intr_t uart_pl011_get_masked_intr_status(
struct uart_pl011_dev_t* dev);
/**
* \brief Returns the UART Raw interrupt status
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Raw interrupt status \ref uart_pl011_intr_t
*
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_intr_t uart_pl011_get_raw_intr_status(
struct uart_pl011_dev_t* dev);
/**
* \brief Sets receive fifo levels
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] rx_lvl Receive fifo levels \ref uart_pl011_rx_fifo_lvl_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_set_rx_fifo_lvl(struct uart_pl011_dev_t* dev,
enum uart_pl011_rx_fifo_lvl_t rx_lvl);
/**
* \brief Sets transmit fifo levels
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] tx_lvl Transmit fifo levels \ref uart_pl011_tx_fifo_lvl_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_set_tx_fifo_lvl(struct uart_pl011_dev_t* dev,
enum uart_pl011_tx_fifo_lvl_t tx_lvl);
/**
* \brief Enables/Disables transmit UART DMA
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] enable To enable/disable the UART transmit DMA
* \ref uart_pl011_tx_dma_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_set_tx_dma(struct uart_pl011_dev_t* dev,
enum uart_pl011_tx_dma_t enable);
/**
* \brief Enables/Disables receive UART DMA
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] enable To enable/disable the UART receive DMA
* \ref uart_pl011_rx_dma_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_set_rx_dma(struct uart_pl011_dev_t* dev,
enum uart_pl011_rx_dma_t enable);
/**
* \brief Check if the UART dev is readable
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true if UART is readable, false otherwise
*
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_is_readable(struct uart_pl011_dev_t* dev);
/**
* \brief Reads one byte from UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[out] byte Pointer to byte that is populated with the data to be read
*
* \return Error status (if any) as specified in
* \ref uart_pl011_error_t
*
* \note This API should only be called when the device is readable
* \ref uart_pl011_is_readable
* \note For better performance, this function doesn't check if dev and byte
* pointer are NULL, and if the driver is initialized.
*/
enum uart_pl011_error_t uart_pl011_read(struct uart_pl011_dev_t* dev,
uint8_t* byte);
/**
* \brief Check if the UART dev is writable
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true if UART is writable, false otherwise
*
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_is_writable(struct uart_pl011_dev_t* dev);
/**
* \brief Writes a byte to UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] byte One byte to write.
*
* \note This API should only be called when the device is writable
* \ref uart_pl011_is_writable
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_write(struct uart_pl011_dev_t* dev, uint8_t byte);
/**
* \brief Sets the UART format.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] word_len UART word length \ref uart_pl011_wlen_t
* \param[in] parity UART parity \ref uart_pl011_parity_t
* \param[in] stop_bits UART stop bits \ref uart_pl011_stopbit_t
*
* \return Returns error code as specified in \ref uart_pl011_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum uart_pl011_error_t uart_pl011_set_format(struct uart_pl011_dev_t* dev,
enum uart_pl011_wlen_t word_len,
enum uart_pl011_parity_t parity,
enum uart_pl011_stopbit_t stop_bits);
/**
* \brief Enables the UART fifo.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_fifo(struct uart_pl011_dev_t* dev);
/**
* \brief Disables the UART fifo.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_fifo(struct uart_pl011_dev_t* dev);
/**
* \brief Enables break transmission from UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_enable_break(struct uart_pl011_dev_t* dev);
/**
* \brief Disables break transmission from UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_disable_break(struct uart_pl011_dev_t* dev);
/**
* \brief Enables CTS flow control in UART PL011
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_cts_flowcontrol(struct uart_pl011_dev_t* dev);
/**
* \brief Disables CTS flow control in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_cts_flowcontrol(struct uart_pl011_dev_t* dev);
/**
* \brief Enables RTS flow control in UART PL011
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_rts_flowcontrol(struct uart_pl011_dev_t* dev);
/**
* \brief Disables RTS flow control in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_rts_flowcontrol(struct uart_pl011_dev_t* dev);
/**
* \brief Enables Data carrier detect in UART PL011
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note For DTE nUARTOut1 can be used as Data carrier detect (DCD).
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_dcd(struct uart_pl011_dev_t* dev);
/**
* \brief Disables Data carrier detect in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \note For DTE nUARTOut1 can be used as Data carrier detect (DCD).
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_dcd(struct uart_pl011_dev_t* dev);
/**
* \brief Enables RTS signal for UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_set_rts(struct uart_pl011_dev_t* dev);
/**
* \brief Disables RTS signal for UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_clear_rts(struct uart_pl011_dev_t* dev);
/**
* \brief Enables DTR signal for UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_set_dtr(struct uart_pl011_dev_t* dev);
/**
* \brief Disables DTR signal for UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_clear_dtr(struct uart_pl011_dev_t* dev);
/**
* \brief Enables reception in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_receive(struct uart_pl011_dev_t* dev);
/**
* \brief Disables reception in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_receive(struct uart_pl011_dev_t* dev);
/**
* \brief Enables transmission in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable_transmit(struct uart_pl011_dev_t* dev);
/**
* \brief Disables transmission in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable_transmit(struct uart_pl011_dev_t* dev);
/**
* \brief Enables loopback in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_set_loopback(struct uart_pl011_dev_t* dev);
/**
* \brief Disables loopback in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_clear_loopback(struct uart_pl011_dev_t* dev);
/**
* \brief Enables IrDA Sir low power mode in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_enable_sirlp(struct uart_pl011_dev_t* dev);
/**
* \brief Disables IrDA Sir in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_disable_sirlp(struct uart_pl011_dev_t* dev);
/**
* \brief Enables IrDA Sir in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_enable_sir(struct uart_pl011_dev_t* dev);
/**
* \brief Disables IrDA Sir in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \note For better performance, this function doesn't check if dev is NULL and
* if the driver is initialized to have better performance.
*/
void uart_pl011_disable_sir(struct uart_pl011_dev_t* dev);
/**
* \brief Enables in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_enable(struct uart_pl011_dev_t* dev);
/**
* \brief Disables in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
*
* \note This function doesn't check if dev is NULL.
*/
void uart_pl011_disable(struct uart_pl011_dev_t* dev);
/**
* \brief Gets the Clear to send status in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true when the modem status input is 0, false otherwise
*
* \note This bit is the complement of the UART clear to send (nUARTCTS) modem
* status input.
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_get_cts_status(struct uart_pl011_dev_t* dev);
/**
* \brief Gets the Data set ready status in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true when the modem status input is 0, false otherwise
*
* \note This bit is the complement of the UART UART data set ready (nUARTDSR)
* modem status input.
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_get_dsr_status(struct uart_pl011_dev_t* dev);
/**
* \brief Gets the Data carrier detect status in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true when the modem status input is 0, false otherwise
*
* \note This bit is the complement of the UART data carrier detect (nUARTDCD)
* modem status input.
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_get_dcd_status(struct uart_pl011_dev_t* dev);
/**
* \brief Gets the Ring indicator status in UART PL011.
*
* \param[in] dev UART PL011 device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true when the modem status input is 0, false otherwise
*
* \note This bit is the complement of the UART ring indicator (nUARTRI) modem
* status input.
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_get_ri_status(struct uart_pl011_dev_t* dev);
/**
* \brief Sets the Low power Divisor in UART dev.
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
* \param[in] value Low power divisor value to be set
*
* \return Returns error code as specified in \ref uart_pl011_error_t
*
* \note For better performance, this function doesn't check if dev is NULL
*/
enum uart_pl011_error_t uart_pl011_set_sirlp_divisor(
struct uart_pl011_dev_t* dev, uint32_t value);
#ifdef __cplusplus
}
#endif
#endif /* __UART_PL011_DRV_H__ */

View File

@ -0,0 +1,141 @@
/* 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.
*/
/*
* This file implements APIS defined in hal/gpio_api.h
* Note: Due to a HW limitation, GPIO in Musca-B1 is Secure only, so secure
* service should be used for GPIO in NS domain.
*/
#include <stddef.h>
#include "gpio_api.h"
#include "pinmap.h"
#include "objects.h"
#include "mbed_error.h"
#include "mbed_assert.h"
#include "rtx_lib.h"
#include "tfm_platform_api.h"
#include "tfm_ioctl_api.h"
#define RETURN_VOID_true return;
#define RETURN_VOID_false return 0;
#define IRQ_MODE_CHECK(is_func_void) \
/* Secure service can't be called in interrupt context. */ \
if (IsIrqMode()) { \
MBED_WARNING(MBED_MAKE_ERROR(MBED_MODULE_HAL, \
MBED_ERROR_INVALID_OPERATION), \
"GPIO secure service can't be called in interrupt context\n"); \
RETURN_VOID_ ## is_func_void \
}
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)
{
obj->pin_num = (uint32_t)NC;
uint32_t result = 0;
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
if (pin >= PA0 && pin <= PA15) {
IRQ_MODE_CHECK(true);
ret = tfm_platform_gpio_init(&result);
if (ret || result) {
return;
}
obj->pin_num = pin;
/* GPIO is input by default */
obj->direction = PIN_INPUT;
return;
}
}
void gpio_mode(gpio_t *obj, PinMode mode)
{
pin_mode(obj->pin_num, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction)
{
uint32_t pin_dir = (direction == PIN_INPUT ? 0 : 1);
uint32_t result = 0;
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
IRQ_MODE_CHECK(true);
ret = tfm_platform_gpio_pin_config(obj->pin_num, pin_dir, &result);
if (ret || result) {
error("gpio_dir failed, error %d, gpio error %d", ret, result);
}
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 tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
uint32_t result = 0;
IRQ_MODE_CHECK(true);
ret = tfm_platform_gpio_pin_write(obj->pin_num, (uint32_t)value, &result);
if (ret || result) {
error("Can not write pin %d; error %d, gpio error %d",
obj->pin_num, ret, result);
}
}
int gpio_read(gpio_t *obj)
{
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
uint32_t result = 0;
uint32_t data = 0;
IRQ_MODE_CHECK(false);
ret = tfm_platform_gpio_pin_read(obj->pin_num, &data, &result);
/* The valid return values of this API are 0 and 1 */
if (ret || result) {
return 0;
} else {
return data;
}
}

View File

@ -0,0 +1,71 @@
/* 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.
*/
/*
* This file implements APIS defined in hal/gpio_irq_api.h
* Note: Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
#include <stddef.h>
#include "gpio_irq_api.h"
#include "objects.h"
#include "mbed_error.h"
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
uint32_t id)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
return 0;
}
void gpio_irq_free(gpio_irq_t *obj)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
}
void gpio_irq_enable(gpio_irq_t *obj)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
}
void gpio_irq_disable(gpio_irq_t *obj)
{
/* Due to a HW limitation, GPIO in Musca-B1 is Secure only, in NS domain,
* GPIO platform service is used. The current implementation of GPIO
* platform service does not support IRQ handling.
*/
}

View File

@ -0,0 +1,89 @@
/* mbed Microcontroller Library
* Copyright (c) 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.
*/
/**
* Low-power elapsed time measure and interval ticker,
* using General Purpose Timer \ref timer_gp_dev_t.
*/
#include "cmsis.h"
#include "device_cfg.h"
#include "timer_gp_drv.h"
#include "lp_ticker_api.h"
/* Check if the module configuration is right. These definitions
are usually located in device_cfg.h */
#ifndef GP_TIMER_DEV
#error "Configuration macro GP_TIMER_DEV is undefined!"
#endif
void lp_ticker_init(void)
{
timer_gp_init(&GP_TIMER_DEV);
NVIC_EnableIRQ(GP_TIMER_ALARM0_IRQ);
timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR);
}
void lp_ticker_free(void)
{
/* This function should stop the ticker from counting, but GP Timer cannot
* be stopped.
*/
timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR);
}
uint32_t lp_ticker_read(void)
{
return timer_gp_get_counter(&GP_TIMER_DEV);
}
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
timer_gp_set_alarm_value(&GP_TIMER_DEV, GP_TIMER_ALARM_NR, (uint32_t)timestamp);
timer_gp_interrupt_enable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR);
}
void lp_ticker_disable_interrupt(void)
{
timer_gp_interrupt_disable(&GP_TIMER_DEV, GP_TIMER_ALARM_NR);
}
void lp_ticker_clear_interrupt(void)
{
timer_gp_interrupt_clear(&GP_TIMER_DEV, GP_TIMER_ALARM_NR);
}
void lp_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(GP_TIMER_ALARM0_IRQ);
}
const ticker_info_t* lp_ticker_get_info(void)
{
static const ticker_info_t info = {
GP_TIMER_FREQ_HZ,
GP_TIMER_BIT_WIDTH
};
return &info;
}
#ifndef GP_TIMER_IRQ0_HANDLER
#error "GP_TIMER_IRQ0_HANDLER should be defined, check device_cfg.h!"
#endif
void GP_TIMER_IRQ0_HANDLER(void)
{
lp_ticker_irq_handler();
}

View File

@ -0,0 +1,137 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-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 "mbed_error.h"
#include "mbed_serial_platform.h"
#include "serial_api.h"
#define UART_DEVICES_NUMBER 2
struct uart_irq_t uart_irq[UART_DEVICES_NUMBER];
const PinMap PinMap_UART_TX[] = {
{UART0_TX, UART_0, ALTERNATE_FUNC_1},
{UART1_TX, UART_1, PRIMARY_FUNC},
{NC, NC, 0}
};
const PinMap PinMap_UART_RX[] = {
{UART0_RX, UART_0, ALTERNATE_FUNC_1},
{UART1_RX, UART_1, PRIMARY_FUNC},
{NC, NC, 0}
};
const PinMap *serial_tx_pinmap()
{
return PinMap_UART_TX;
}
const PinMap *serial_rx_pinmap()
{
return PinMap_UART_RX;
}
#ifdef UART0_PL011_DEV
#ifndef uart0_tx_irq_handler
#error "uart0_tx_irq_handler should be defined, check device_cfg.h!"
#endif
void uart0_tx_irq_handler(void)
{
uart_pl011_clear_intr(&UART0_PL011_DEV, UART_PL011_TX_INTR_MASK);
if(uart_irq[UART_0].handler != 0) {
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
}
}
#ifndef uart0_rx_irq_handler
#error "uart0_rx_irq_handler should be defined, check device_cfg.h!"
#endif
void uart0_rx_irq_handler(void)
{
uart_pl011_clear_intr(&UART0_PL011_DEV, UART_PL011_RX_INTR_MASK);
if(uart_irq[UART_0].handler != 0) {
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
}
}
#ifndef uart0_rx_timeout_irq_handler
#error "uart0_rx_timeout_irq_handler should be defined, check device_cfg.h!"
#endif
void uart0_rx_timeout_irq_handler(void)
{
if(uart_irq[UART_0].handler != 0) {
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
}
}
#endif
#ifdef UART1_PL011_DEV
#ifndef uart1_tx_irq_handler
#error "uart1_tx_irq_handler should be defined, check device_cfg.h!"
#endif
void uart1_tx_irq_handler(void)
{
uart_pl011_clear_intr(&UART1_PL011_DEV, UART_PL011_TX_INTR_MASK);
if(uart_irq[UART_1].handler != 0) {
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
}
}
#ifndef uart1_rx_irq_handler
#error "uart1_rx_irq_handler should be defined, check device_cfg.h!"
#endif
void uart1_rx_irq_handler(void)
{
uart_pl011_clear_intr(&UART1_PL011_DEV, UART_PL011_RX_INTR_MASK);
if(uart_irq[UART_1].handler != 0) {
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
}
}
#ifndef uart1_rx_timeout_irq_handler
#error "uart1_rx_timeout_irq_handler should be defined, check device_cfg.h!"
#endif
void uart1_rx_timeout_irq_handler(void)
{
if(uart_irq[UART_1].handler != 0) {
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
}
}
#endif
void mbed_uart_platform_init(serial_t *obj, UARTName uart)
{
switch (uart) {
#ifdef UART0_PL011_DEV
case UART_0:
obj->uart_dev = &UART0_PL011_DEV;
obj->tx_irq = UART0_Tx_IRQn;
obj->rx_irq = UART0_Rx_IRQn;
obj->rx_timeout_irq = UART0_RxTimeout_IRQn;
break;
#endif
#ifdef UART1_PL011_DEV
case UART_1:
obj->uart_dev = &UART1_PL011_DEV;
obj->tx_irq = UART1_Tx_IRQn;
obj->rx_irq = UART1_Rx_IRQn;
obj->rx_timeout_irq = UART1_RxTimeout_IRQn;
break;
#endif
default:
error("serial_init: No uart selected");
}
}

View File

@ -0,0 +1,42 @@
/*
* 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 __MBED_SERIAL_PLATFORM_H__
#define __MBED_SERIAL_PLATFORM_H__
#include "serial_api.h"
#ifdef __cplusplus
extern "C" {
#endif
struct uart_irq_t {
uart_irq_handler handler;
uint32_t id;
};
/* Handlers registered */
extern struct uart_irq_t uart_irq[];
void mbed_uart_platform_init(serial_t *obj, UARTName uart);
#ifdef __cplusplus
}
#endif
#endif /* __SERIAL_PLATFORM_H__ */

View File

@ -0,0 +1,132 @@
/* 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 "objects.h"
#include "pinmap.h"
#include "musca_b1_scc_drv.h"
#include "tfm_ioctl_api.h"
#include "rtx_lib.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;
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
MBED_ASSERT(pin != NC);
/* Secure service can't be called in interrupt context. */
if (IsIrqMode()) {
MBED_WARNING(MBED_MAKE_ERROR(MBED_MODULE_HAL,
MBED_ERROR_INVALID_OPERATION),
"Pin secure service can't be called in interrupt context\n");
return;
}
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;
}
ret = tfm_platform_set_pin_alt_func(flags, (1u<<pin), &result);
if (result != SCC_ERR_NONE) {
error("Can not set pin alt func %d", pin);
}
if (ret != TFM_PLATFORM_ERR_SUCCESS) {
error("tfm_platform_set_pin_alt_func failed for pin %d", pin);
}
}
/**
* \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)
{
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SUCCESS;
uint32_t result = 0;
MBED_ASSERT(pin != NC);
/* Secure service can't be called in interrupt context. */
if (IsIrqMode()) {
MBED_WARNING(MBED_MAKE_ERROR(MBED_MODULE_HAL,
MBED_ERROR_INVALID_OPERATION),
"Pin secure service can't be called in interrupt context\n");
return;
}
ret = tfm_platform_set_pin_mode((1u<<pin), translate_pinmode(mode),
&result);
if (result != SCC_ERR_NONE) {
error("Can not set pin mode %d", pin);
}
if (ret != TFM_PLATFORM_ERR_SUCCESS) {
error("tfm_platform_set_pin_mode failed for pin %d", pin);
}
}

View File

@ -0,0 +1,49 @@
Permissive Binary License
Version 1.0, December 2020
Redistribution. Redistribution and use in binary form, without
modification, are permitted provided that the following conditions are
met:
1) Redistributions must reproduce the above copyright notice and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
2) Unless to the extent explicitly permitted by law, no reverse
engineering, decompilation, or disassembly of this software is
permitted.
3) Redistribution as part of a software development kit must include the
accompanying file named DEPENDENCIES and any dependencies listed in
that file.
4) Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Limited patent license. The copyright holders (and contributors) grant a
worldwide, non-exclusive, no-charge, royalty-free patent license to
make, have made, use, offer to sell, sell, import, and otherwise
transfer this software, where such license applies only to those patent
claims licensable by the copyright holders (and contributors) that are
necessarily infringed by this software. This patent license shall not
apply to any combinations that include this software. No hardware is
licensed hereunder.
If you institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the software
itself infringes your patent(s), then your rights granted under this
license shall terminate as of the date such litigation is filed.
DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,49 @@
# MUSCA_B1_NS prebuilt secure binaries
This directory tree contains Secure images released under Permissive Binary License.
Built by mbed-cli using GNU Arm Embedded - version 8.3.1
These images were compiled by the following command:
## mcuboot.bin
### Repository
https://git.trustedfirmware.org/trusted-firmware-m.git
### Commit SHA
6c5be4a98e4d7055ee49076ca4e515fb4b172e66
```sh
cmake ../ -G"Unix Makefiles" -DTARGET_PLATFORM=MUSCA_B1 -DCOMPILER=ARMCLANG -DCMAKE_BUILD_TYPE=Debug
make
```
## tfm.bin
```sh
mbed compile -t GCC_ARM -m ARM_MUSCA_B1_S --app-config tools/psa/tfm/mbed_app.json --profile release
```
## spm_smoke.bin
```sh
mbed test --compile -t GCC_ARM -m ARM_MUSCA_B1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_smoke -DUSE_PSA_TEST_PARTITIONS -DUSE_SMOKE_TESTS_PART1 --profile release
```
## spm_client.bin
```sh
mbed test --compile -t GCC_ARM -m ARM_MUSCA_B1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_client -DUSE_PSA_TEST_PARTITIONS -DUSE_CLIENT_TESTS_PART1 --profile release
```
## spm_server.bin
```sh
mbed test --compile -t GCC_ARM -m ARM_MUSCA_B1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-spm_server -DUSE_PSA_TEST_PARTITIONS -DUSE_SERVER_TESTS_PART1 -DUSE_SERVER_TESTS_PART2 --profile release
```
## crypto_access_control.bin
```sh
mbed test --compile -t GCC_ARM -m ARM_MUSCA_B1_S --app-config tools/psa/tfm/mbed_app.json -n tests-psa-crypto_access_control -DUSE_PSA_TEST_PARTITIONS -DUSE_CRYPTO_ACL_TEST --profile release
```
To update the prebuilt binaries run the previous commands.

View File

@ -0,0 +1,215 @@
/* mbed Microcontroller Library
* Copyright (c) 2017-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 <string.h>
#include "mbed_error.h"
#include "objects.h"
#include "pinmap.h"
#include "serial_api.h"
#include "mbed_serial_platform.h"
#define STDIO_UART_NOT_INITED 0
#define STDIO_UART_INITED 1
extern const PinMap PinMap_UART_TX[];
extern const PinMap PinMap_UART_RX[];
/* Global variables needed for mbed */
int stdio_uart_inited = STDIO_UART_NOT_INITED;
serial_t stdio_uart;
void serial_init(serial_t *obj, PinName tx, PinName rx)
{
/* Determine the UART to use */
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
if (uart == (UARTName)NC) {
error("Serial pinout mapping failed");
}
mbed_uart_platform_init(obj, uart);
obj->uart_index = uart;
/* Pinout the chosen uart */
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
uart_pl011_init(obj->uart_dev, SystemCoreClock);
uart_pl011_set_baudrate(obj->uart_dev,
MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
uart_pl011_enable(obj->uart_dev);
if (uart == STDIO_UART) {
stdio_uart_inited = STDIO_UART_INITED;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj)
{
uart_pl011_uninit(obj->uart_dev);
}
void serial_baud(serial_t *obj, int baudrate)
{
if(uart_pl011_set_baudrate(obj->uart_dev,baudrate) != UART_PL011_ERR_NONE) {
error("serial_baud: invalid baudrate");
}
}
void serial_format(serial_t *obj, int data_bits, SerialParity parity,
int stop_bits)
{
enum uart_pl011_wlen_t uart_word_len = UART_PL011_WLEN_8;
enum uart_pl011_parity_t uart_parity = UART_PL011_PARITY_DISABLED;
enum uart_pl011_stopbit_t uart_stop_bits = UART_PL011_STOPBIT_1;
switch (data_bits) {
case 5:
uart_word_len = UART_PL011_WLEN_5;
break;
case 6:
uart_word_len = UART_PL011_WLEN_6;
break;
case 7:
uart_word_len = UART_PL011_WLEN_7;
break;
case 8:
uart_word_len = UART_PL011_WLEN_8;
break;
default:
error("serial_format: unexpected data bits");
}
switch (parity) {
case ParityNone:
uart_parity = UART_PL011_PARITY_DISABLED;
break;
case ParityOdd:
uart_parity = UART_PL011_PARITY_ODD;
break;
case ParityEven:
uart_parity = UART_PL011_PARITY_EVEN;
break;
case ParityForced1:
uart_parity = UART_PL011_PARITY_STICKY_ONE;
break;
case ParityForced0:
uart_parity = UART_PL011_PARITY_STICKY_ZERO;
break;
default:
error("serial_format: unexpected parity");
}
switch (stop_bits) {
case 1:
uart_stop_bits = UART_PL011_STOPBIT_1;
break;
case 2:
uart_stop_bits = UART_PL011_STOPBIT_2;
break;
default:
error("serial_format: unexpected stop bit");
}
(void)uart_pl011_set_format(obj->uart_dev,
uart_word_len, uart_parity, uart_stop_bits);
}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
{
uart_irq[obj->uart_index].handler = handler;
uart_irq[obj->uart_index].id = id;
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
{
switch(irq) {
case RxIrq:
if (enable) {
NVIC_EnableIRQ(obj->rx_irq);
uart_pl011_enable_intr(obj->uart_dev, UART_PL011_RX_INTR_MASK);
NVIC_EnableIRQ(obj->rx_timeout_irq);
uart_pl011_enable_intr(obj->uart_dev, UART_PL011_RT_INTR_MASK);
} else {
uart_pl011_disable_intr(obj->uart_dev, UART_PL011_RX_INTR_MASK);
NVIC_DisableIRQ(obj->rx_irq);
uart_pl011_disable_intr(obj->uart_dev, UART_PL011_RT_INTR_MASK);
NVIC_DisableIRQ(obj->rx_timeout_irq);
}
break;
case TxIrq:
if (enable) {
NVIC_EnableIRQ(obj->tx_irq);
uart_pl011_enable_intr(obj->uart_dev, UART_PL011_TX_INTR_MASK);
} else {
uart_pl011_disable_intr(obj->uart_dev, UART_PL011_TX_INTR_MASK);
NVIC_DisableIRQ(obj->tx_irq);
}
break;
default : return;
}
}
int serial_readable(serial_t *obj)
{
return (int)uart_pl011_is_readable(obj->uart_dev);
}
int serial_writable(serial_t *obj)
{
return (int)uart_pl011_is_writable(obj->uart_dev);
}
int serial_getc(serial_t *obj)
{
uint8_t byte = 0;
while(!uart_pl011_is_readable(obj->uart_dev));
(void)uart_pl011_read(obj->uart_dev, &byte);
return byte;
}
void serial_putc(serial_t *obj, int c)
{
while(!uart_pl011_is_writable(obj->uart_dev));
uart_pl011_write(obj->uart_dev, (uint8_t)c);
}
void serial_clear(serial_t *obj)
{
uart_pl011_write(obj->uart_dev, (uint8_t)0);
}
void serial_pinout_tx(PinName tx)
{
pinmap_pinout(tx, PinMap_UART_TX);
}
void serial_break_set(serial_t *obj)
{
uart_pl011_enable_break(obj->uart_dev);
}
void serial_break_clear(serial_t *obj)
{
uart_pl011_disable_break(obj->uart_dev);
}
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow,
PinName txflow)
{
error("serial_set_flow_control: Flow control is not supported in MUSCA");
}

View File

@ -0,0 +1,48 @@
/* 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_cfg.h"
#include "sleep_api.h"
#include "timer_cmsdk_drv.h"
#if DEVICE_SLEEP
void hal_sleep(void)
{
__WFI();
}
/* Since there is no power management implemented in Musca-A, Deep Sleep could
* be supported only by additional software components, registering and managing
* the currently configured IPs. This would also mean a huge implementation
* overhead, that is not intended to be added. Therefore, Deep Sleep is almost
* identical to Sleep, representing a "Waiting For Interrupt" state, and
* disabling the Microsec ticker in addition.
*/
void hal_deepsleep(void)
{
#ifdef USEC_TIMER_DEV
timer_cmsdk_disable(&USEC_TIMER_DEV);
#endif
__WFI();
#ifdef USEC_TIMER_DEV
timer_cmsdk_enable(&USEC_TIMER_DEV);
#endif
}
#endif

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "tfm_platform_api.h"
#include "tfm_ioctl_api.h"
enum tfm_platform_err_t
tfm_platform_set_pin_alt_func(uint32_t alt_func, uint64_t pin_mask,
uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_pin_service_args_t args;
if (result == NULL) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args.type = TFM_PIN_SERVICE_TYPE_SET_ALTFUNC;
args.u.set_altfunc.alt_func = alt_func;
args.u.set_altfunc.pin_mask = pin_mask;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)result;
out_vec.len = sizeof(*result);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_PIN_SERVICE,
&in_vec,
&out_vec);
return ret;
}
enum tfm_platform_err_t
tfm_platform_set_pin_default_in(uint32_t alt_func, uint32_t pin_value,
bool default_in_value, uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_pin_service_args_t args;
if (result == NULL) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args.type = TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN;
args.u.set_default_in.alt_func = alt_func;
args.u.set_default_in.pin_value = pin_value;
args.u.set_default_in.default_in_value = default_in_value;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)result;
out_vec.len = sizeof(*result);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_PIN_SERVICE,
&in_vec,
&out_vec);
return ret;
}
enum tfm_platform_err_t
tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_pin_service_args_t args;
if (result == NULL) {
return TFM_PLATFORM_ERR_INVALID_PARAM;
}
args.type = TFM_PIN_SERVICE_TYPE_SET_PIN_MODE;
args.u.set_pin_mode.pin_mask = pin_mask;
args.u.set_pin_mode.pin_mode = pin_mode;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)result;
out_vec.len = sizeof(*result);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_PIN_SERVICE,
&in_vec,
&out_vec);
return ret;
}
enum tfm_platform_err_t tfm_platform_gpio_init(uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_INIT;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.result;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_pin_config(uint32_t pin_num, uint32_t direction,
uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PIN_CONFIG;
args.u.gpio_config.pin_num_or_mask = pin_num;
args.u.gpio_config.direction = direction;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.result;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_pin_write(uint32_t pin_num, uint32_t value, uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PIN_WRITE;
args.u.gpio_write.pin_num_or_mask = pin_num;
args.u.gpio_write.value = value;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.result;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_pin_read(uint32_t pin_num, uint32_t *data, uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PIN_READ;
args.u.gpio_read.pin_num_or_mask = pin_num;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.gpio_read_result.result;
*data = out.u.gpio_read_result.data;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_port_config(uint32_t pin_mask, uint32_t direction,
uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PORT_CONFIG;
args.u.gpio_config.pin_num_or_mask = pin_mask;
args.u.gpio_config.direction = direction;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.result;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_port_write(uint32_t pin_mask, uint32_t value,
uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PORT_WRITE;
args.u.gpio_write.pin_num_or_mask = pin_mask;
args.u.gpio_write.value = value;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.result;
return ret;
}
enum tfm_platform_err_t
tfm_platform_gpio_port_read(uint32_t pin_mask, uint32_t *data, uint32_t *result)
{
enum tfm_platform_err_t ret;
psa_invec in_vec;
psa_outvec out_vec;
struct tfm_gpio_service_args_t args;
struct tfm_gpio_service_out_t out;
args.type = TFM_GPIO_SERVICE_TYPE_PORT_READ;
args.u.gpio_read.pin_num_or_mask = pin_mask;
in_vec.base = (const void *)&args;
in_vec.len = sizeof(args);
out_vec.base = (void *)&out;
out_vec.len = sizeof(out);
ret = tfm_platform_ioctl(TFM_PLATFORM_IOCTL_GPIO_SERVICE,
&in_vec,
&out_vec);
*result = out.u.gpio_read_result.result;
*data = out.u.gpio_read_result.data;
return ret;
}

View File

@ -0,0 +1,124 @@
/* mbed Microcontroller Library
* 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.
*/
/**
* Supports the High-resolution Ticker for mbed by implementing
* \ref us_ticker_api.h, using a CMSDK Timer \ref timer_cmsdk_dev_t.
*/
#include "device.h"
#include "mbed_critical.h"
#include "timer_cmsdk_drv.h"
#include "us_ticker_api.h"
static uint64_t total_ticks = 0;
/* Stores the last reload value, or the last tick value read when a read API
* call occurs from the upper layer, needed to keep total_ticks
* accumulated properly.
*/
static uint32_t previous_ticks = 0;
static void restart_timer(uint32_t new_reload)
{
timer_cmsdk_disable(&USEC_TIMER_DEV);
timer_cmsdk_set_reload_value(&USEC_TIMER_DEV,
new_reload);
timer_cmsdk_reset(&USEC_TIMER_DEV);
timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV);
timer_cmsdk_enable_interrupt(&USEC_TIMER_DEV);
timer_cmsdk_enable(&USEC_TIMER_DEV);
}
static void update_ticker(void)
{
if (timer_cmsdk_is_interrupt_active(&USEC_TIMER_DEV)) {
total_ticks += previous_ticks;
previous_ticks = TIMER_CMSDK_MAX_RELOAD;
restart_timer(previous_ticks);
} else {
uint32_t tick = timer_cmsdk_get_current_value(&USEC_TIMER_DEV);
if (tick < previous_ticks) {
uint32_t delta = previous_ticks - tick;
total_ticks += delta;
previous_ticks = tick;
}
}
}
void us_ticker_init(void)
{
timer_cmsdk_init(&USEC_TIMER_DEV);
previous_ticks = TIMER_CMSDK_MAX_RELOAD;
NVIC_EnableIRQ(USEC_INTERVAL_IRQ);
restart_timer(previous_ticks);
}
void us_ticker_free(void)
{
timer_cmsdk_disable(&USEC_TIMER_DEV);
}
uint32_t us_ticker_read(void)
{
core_util_critical_section_enter();
update_ticker();
core_util_critical_section_exit();
return (uint32_t)(total_ticks >> USEC_REPORTED_SHIFT);
}
void us_ticker_set_interrupt(timestamp_t timestamp)
{
uint32_t reload = (timestamp - us_ticker_read()) << USEC_REPORTED_SHIFT;
previous_ticks = reload;
restart_timer(previous_ticks);
}
void us_ticker_disable_interrupt(void)
{
timer_cmsdk_disable_interrupt(&USEC_TIMER_DEV);
}
void us_ticker_clear_interrupt(void)
{
timer_cmsdk_clear_interrupt(&USEC_TIMER_DEV);
}
void us_ticker_fire_interrupt(void)
{
NVIC_SetPendingIRQ(USEC_INTERVAL_IRQ);
}
const ticker_info_t* us_ticker_get_info()
{
static const ticker_info_t info = {
USEC_REPORTED_FREQ_HZ,
USEC_REPORTED_BITS
};
return &info;
}
#ifndef usec_interval_irq_handler
#error "usec_interval_irq_handler should be defined, check device_cfg.h!"
#endif
void usec_interval_irq_handler(void)
{
update_ticker();
us_ticker_irq_handler();
}

View File

@ -0,0 +1,132 @@
/*
* 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

@ -0,0 +1,48 @@
/*
* 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

@ -0,0 +1,69 @@
/*
* 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

@ -0,0 +1,152 @@
/*
* 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

@ -0,0 +1,970 @@
/*
* 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

@ -0,0 +1,115 @@
/*
* 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

@ -0,0 +1,901 @@
/*
* 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

@ -0,0 +1,271 @@
/*
* 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

@ -0,0 +1,153 @@
#! 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

@ -0,0 +1,291 @@
;/*
; * 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

@ -0,0 +1,366 @@
;/*
; * 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

@ -0,0 +1,401 @@
;/*
; * 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

@ -0,0 +1,791 @@
/*
* 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

@ -0,0 +1,354 @@
/*
* 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

@ -0,0 +1,152 @@
/*
* 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

@ -0,0 +1,143 @@
/*
* 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

@ -0,0 +1,347 @@
/*
* 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

@ -0,0 +1,201 @@
/*
* 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

@ -0,0 +1,755 @@
/*
* 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

@ -0,0 +1,416 @@
/*
* 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

@ -0,0 +1,138 @@
/* 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

@ -0,0 +1,102 @@
/* 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

@ -0,0 +1,115 @@
/* 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

@ -0,0 +1,324 @@
/*
* 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

@ -0,0 +1,524 @@
/*
* 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 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

@ -0,0 +1,126 @@
/*
* 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

@ -0,0 +1,17 @@
/*
* 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

@ -0,0 +1,183 @@
/*
* 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

@ -0,0 +1,24 @@
/* 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.
*/
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#include "objects.h"
#endif

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2017-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.
*/
#ifndef __MUSCA_B1_CMSIS_H__
#define __MUSCA_B1_CMSIS_H__
/* Processor and Core Peripherals and Configurations */
/* ========================================================================== */
/* ============= Processor and Core Peripheral Section ============= */
/* ========================================================================== */
/* ----- Start of section using anonymous unions and disabling warnings ----- */
#if defined (__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined (__ICCARM__)
#pragma language=extended
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc11-extensions"
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#elif defined (__GNUC__)
/* anonymous unions are enabled by default */
#elif defined (__TMS470__)
/* anonymous unions are enabled by default */
#elif defined (__TASKING__)
#pragma warning 586
#elif defined (__CSMC__)
/* anonymous unions are enabled by default */
#else
#warning Not supported compiler type
#endif
/* ----- Configuration of the Cortex-M33 Processor and Core Peripherals ----- */
/* ----- This configuration can be applied to either of the cores ----------- */
#define __CM33_REV 0x0002U /* Core revision r0p2 */
#define __SAUREGION_PRESENT 1U /* SAU regions present */
#define __MPU_PRESENT 1U /* MPU present */
#define __VTOR_PRESENT 1U /* VTOR present */
#define __NVIC_PRIO_BITS 4U /* Number of Bits used for the
* Priority Levels */
#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick
* Config is used */
#define __FPU_PRESENT 1U /* FPU present */
#define __DSP_PRESENT 1U /* DSP extension present */
#include "system_core_init.h"
#include "platform_irq.h"
#include <core_cm33.h> /*!< ARM Cortex-M33 processor and core peripherals */
/* ------ End of section using anonymous unions and disabling warnings ------ */
#if defined (__CC_ARM)
#pragma pop
#elif defined (__ICCARM__)
/* leave anonymous unions enabled */
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic pop
#elif defined (__GNUC__)
/* anonymous unions are enabled by default */
#elif defined (__TMS470__)
/* anonymous unions are enabled by default */
#elif defined (__TASKING__)
#pragma warning restore
#elif defined (__CSMC__)
/* anonymous unions are enabled by default */
#else
#warning Not supported compiler type
#endif
#endif /*__MUSCA_B1_CMSIS_H__ */

View File

@ -0,0 +1,132 @@
/*
* 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.
*/
#ifndef __MUSCA_B1_DEVICE_CFG_H__
#define __MUSCA_B1_DEVICE_CFG_H__
/**
* \file device_cfg.h
* \brief Configuration file native driver re-targeting
*
* \details This file can be used to add native driver specific macro
* definitions to select which peripherals are available in the build.
*
* 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
#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
#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
/* CMSDK Timers */
#define CMSDK_TIMER0_NS
#define CMSDK_TIMER0_DEV CMSDK_TIMER0_DEV_NS
#define CMSDK_TIMER1_NS
/* GPIO */
#define GPIO0_CMSDK_NS
#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_NS;
/* GP Timer */
#define GP_TIMER_NS
#define GP_TIMER_DEV GP_TIMER_DEV_NS
#define GP_TIMER_ALARM0_IRQ GpTimer0_IRQn
#define GP_TIMER_IRQ0_HANDLER GpTimer0_IRQHandler
#define GP_TIMER_ALARM_NR TIMER_GP_READ_ALARM_0
#define GP_TIMER_FREQ_HZ 32768UL /* System Ref Clock */
#define GP_TIMER_BIT_WIDTH 32U
/**
* mbed usec high-resolution ticker configuration
*/
#define USEC_TIMER_DEV CMSDK_TIMER0_DEV_NS
#define usec_interval_irq_handler TIMER0_IRQHandler
#define USEC_INTERVAL_IRQ TIMER0_IRQn
/** Timer frequency is equal to SYSTEM_CLOCK, defined in system_core_clk.c */
#define TIMER_FREQ_HZ 40960000U
/** The us Ticker uses CMSDK Timer, that does not have HW prescaler.
* The reported shift define is necessary for the software emulated
* prescaler behavior, so the ticker works as if it was ticking on a
* virtually slower frequency. The value 5 sets up the ticker to work
* properly in the specified frequency interval.
*/
#define USEC_REPORTED_SHIFT 6
#define USEC_REPORTED_FREQ_HZ (TIMER_FREQ_HZ >> USEC_REPORTED_SHIFT)
#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__ */

View File

@ -0,0 +1,601 @@
/*
* 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.
*/
/**
* \file device_definition.c
* \brief This file defines exports the structures based on the peripheral
* definitions from device_cfg.h.
* This file is meant to be used as a helper for baremetal
* applications and/or as an example of how to configure the generic
* driver structures.
*/
#include "device_cfg.h"
#include "device_definition.h"
#include "platform_base_address.h"
/* ======= Peripheral configuration structure definitions ======= */
/* MUSCA B1 SCC driver structures */
#ifdef MUSCA_B1_SCC_S
static const struct musca_b1_scc_dev_cfg_t MUSCA_B1_SCC_DEV_CFG_S = {
.base = MUSCA_B1_SCC_S_BASE};
struct musca_b1_scc_dev_t MUSCA_B1_SCC_DEV_S = {&(MUSCA_B1_SCC_DEV_CFG_S)};
#endif
/* ARM PPC SSE 200 driver structures */
#ifdef AHB_PPC0_S
static struct ppc_sse200_dev_cfg_t AHB_PPC0_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t AHB_PPC0_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t AHB_PPC0_DEV_S = {
&AHB_PPC0_DEV_CFG_S, &AHB_PPC0_DEV_DATA_S };
#endif
#ifdef AHB_PPCEXP0_S
static struct ppc_sse200_dev_cfg_t AHB_PPCEXP0_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t AHB_PPCEXP0_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t AHB_PPCEXP0_DEV_S = {
&AHB_PPCEXP0_DEV_CFG_S, &AHB_PPCEXP0_DEV_DATA_S };
#endif
#ifdef AHB_PPCEXP1_S
static struct ppc_sse200_dev_cfg_t AHB_PPCEXP1_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t AHB_PPCEXP1_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t AHB_PPCEXP1_DEV_S = {
&AHB_PPCEXP1_DEV_CFG_S, &AHB_PPCEXP1_DEV_DATA_S };
#endif
#ifdef AHB_PPCEXP2_S
static struct ppc_sse200_dev_cfg_t AHB_PPCEXP2_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t AHB_PPCEXP2_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t AHB_PPCEXP2_DEV_S = {
&AHB_PPCEXP2_DEV_CFG_S, &AHB_PPCEXP2_DEV_DATA_S };
#endif
#ifdef AHB_PPCEXP3_S
static struct ppc_sse200_dev_cfg_t AHB_PPCEXP3_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t AHB_PPCEXP3_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t AHB_PPCEXP3_DEV_S = {
&AHB_PPCEXP3_DEV_CFG_S, &AHB_PPCEXP3_DEV_DATA_S };
#endif
#ifdef APB_PPC0_S
static struct ppc_sse200_dev_cfg_t APB_PPC0_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPC0_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPC0_DEV_S = {
&APB_PPC0_DEV_CFG_S, &APB_PPC0_DEV_DATA_S };
#endif
#ifdef APB_PPC1_S
static struct ppc_sse200_dev_cfg_t APB_PPC1_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPC1_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPC1_DEV_S = {
&APB_PPC1_DEV_CFG_S, &APB_PPC1_DEV_DATA_S};
#endif
#ifdef APB_PPCEXP0_S
static struct ppc_sse200_dev_cfg_t APB_PPCEXP0_DEV_CFG_S = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPCEXP0_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPCEXP0_DEV_S = {
&APB_PPCEXP0_DEV_CFG_S, &APB_PPCEXP0_DEV_DATA_S };
#endif
#ifdef APB_PPCEXP1_S
static struct ppc_sse200_dev_cfg_t APB_PPCEXP1_DEV_CFG = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPCEXP1_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPCEXP1_DEV_S = {
&APB_PPCEXP1_DEV_CFG, &APB_PPCEXP1_DEV_DATA_S };
#endif
#ifdef APB_PPCEXP2_S
static struct ppc_sse200_dev_cfg_t APB_PPCEXP2_DEV_CFG = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPCEXP2_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPCEXP2_DEV_S = {
&APB_PPCEXP2_DEV_CFG, &APB_PPCEXP2_DEV_DATA_S };
#endif
#ifdef APB_PPCEXP3_S
static struct ppc_sse200_dev_cfg_t APB_PPCEXP3_DEV_CFG = {
.spctrl_base = MUSCA_B1_SPCTRL_S_BASE,
.nspctrl_base = MUSCA_B1_NSPCTRL_NS_BASE };
static struct ppc_sse200_dev_data_t APB_PPCEXP3_DEV_DATA_S = {
.p_ns_ppc = 0,
.p_sp_ppc = 0,
.p_nsp_ppc = 0,
.int_bit_mask = 0,
.state = 0 };
struct ppc_sse200_dev_t APB_PPCEXP3_DEV_S = {
&APB_PPCEXP3_DEV_CFG, &APB_PPCEXP3_DEV_DATA_S };
#endif
/* ARM MPC SIE 200 driver structures */
#ifdef MPC_ISRAM0_S
static const struct mpc_sie_dev_cfg_t MPC_ISRAM0_DEV_CFG_S = {
.base = MUSCA_B1_MPC_SRAM0_S_BASE};
static struct mpc_sie_dev_data_t MPC_ISRAM0_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_ISRAM0_DEV_S = {
&(MPC_ISRAM0_DEV_CFG_S),
&(MPC_ISRAM0_DEV_DATA_S)};
#endif
#ifdef MPC_ISRAM1_S
static const struct mpc_sie_dev_cfg_t MPC_ISRAM1_DEV_CFG_S = {
.base = MUSCA_B1_MPC_SRAM1_S_BASE};
static struct mpc_sie_dev_data_t MPC_ISRAM1_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_ISRAM1_DEV_S = {
&(MPC_ISRAM1_DEV_CFG_S),
&(MPC_ISRAM1_DEV_DATA_S)};
#endif
#ifdef MPC_ISRAM2_S
static const struct mpc_sie_dev_cfg_t MPC_ISRAM2_DEV_CFG_S = {
.base = MUSCA_B1_MPC_SRAM2_S_BASE};
static struct mpc_sie_dev_data_t MPC_ISRAM2_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_ISRAM2_DEV_S = {
&(MPC_ISRAM2_DEV_CFG_S),
&(MPC_ISRAM2_DEV_DATA_S)};
#endif
#ifdef MPC_ISRAM3_S
static const struct mpc_sie_dev_cfg_t MPC_ISRAM3_DEV_CFG_S = {
.base = MUSCA_B1_MPC_SRAM3_S_BASE};
static struct mpc_sie_dev_data_t MPC_ISRAM3_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_ISRAM3_DEV_S = {
&(MPC_ISRAM3_DEV_CFG_S),
&(MPC_ISRAM3_DEV_DATA_S)};
#endif
#ifdef MPC_CODE_SRAM_S
static const struct mpc_sie_dev_cfg_t MPC_CODE_SRAM_DEV_CFG_S = {
.base = MUSCA_B1_CODE_SRAM_MPC_S_BASE};
static struct mpc_sie_dev_data_t MPC_CODE_SRAM_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_CODE_SRAM_DEV_S = {
&(MPC_CODE_SRAM_DEV_CFG_S),
&(MPC_CODE_SRAM_DEV_DATA_S)};
#endif
#ifdef MPC_QSPI_S
static const struct mpc_sie_dev_cfg_t MPC_QSPI_DEV_CFG_S = {
.base = MUSCA_B1_QSPI_MPC_S_BASE};
static struct mpc_sie_dev_data_t MPC_QSPI_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_QSPI_DEV_S = {
&(MPC_QSPI_DEV_CFG_S),
&(MPC_QSPI_DEV_DATA_S)};
#endif
#ifdef MPC_EFLASH0_S
static const struct mpc_sie_dev_cfg_t MPC_EFLASH0_DEV_CFG_S = {
.base = MUSCA_B1_EFLASH0_MPC_S_BASE};
static struct mpc_sie_dev_data_t MPC_EFLASH0_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_EFLASH0_DEV_S = {
&(MPC_EFLASH0_DEV_CFG_S),
&(MPC_EFLASH0_DEV_DATA_S)};
#endif
#ifdef MPC_EFLASH1_S
static const struct mpc_sie_dev_cfg_t MPC_EFLASH1_DEV_CFG_S = {
.base = MUSCA_B1_EFLASH1_MPC_S_BASE};
static struct mpc_sie_dev_data_t MPC_EFLASH1_DEV_DATA_S = {
.range_list = 0,
.nbr_of_ranges = 0,
.is_initialized = false};
struct mpc_sie_dev_t MPC_EFLASH1_DEV_S = {
&(MPC_EFLASH1_DEV_CFG_S),
&(MPC_EFLASH1_DEV_DATA_S)};
#endif
/** CMSDK GPIO driver structures */
#ifdef GPIO0_CMSDK_S
static const struct gpio_cmsdk_dev_cfg_t GPIO0_CMSDK_DEV_CFG_S = {
.base = MUSCA_B1_GPIO_S_BASE};
struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_S = {&(GPIO0_CMSDK_DEV_CFG_S)};
#endif
/** ARM UART PL011 driver structures */
#ifdef UART0_PL011_S
static const struct uart_pl011_dev_cfg_t UART0_PL011_DEV_CFG_S = {
.base = MUSCA_B1_UART0_S_BASE,
.def_baudrate = UART_DEFAULT_BAUD_RATE,
.def_wlen = UART_PL011_WLEN_8,
.def_parity = UART_PL011_PARITY_DISABLED,
.def_stopbit = UART_PL011_STOPBIT_1};
static struct uart_pl011_dev_data_t UART0_PL011_DEV_DATA_S = {
.state = 0,
.uart_clk = 0,
.baudrate = 0};
struct uart_pl011_dev_t UART0_PL011_DEV_S = {&(UART0_PL011_DEV_CFG_S),
&(UART0_PL011_DEV_DATA_S)};
#endif
#ifdef UART0_PL011_NS
static const struct uart_pl011_dev_cfg_t UART0_PL011_DEV_CFG_NS = {
.base = MUSCA_B1_UART0_NS_BASE,
.def_baudrate = UART_DEFAULT_BAUD_RATE,
.def_wlen = UART_PL011_WLEN_8,
.def_parity = UART_PL011_PARITY_DISABLED,
.def_stopbit = UART_PL011_STOPBIT_1};
static struct uart_pl011_dev_data_t UART0_PL011_DEV_DATA_NS = {
.state = 0,
.uart_clk = 0,
.baudrate = 0};
struct uart_pl011_dev_t UART0_PL011_DEV_NS = {&(UART0_PL011_DEV_CFG_NS),
&(UART0_PL011_DEV_DATA_NS)};
#endif
#ifdef UART1_PL011_S
static const struct uart_pl011_dev_cfg_t UART1_PL011_DEV_CFG_S = {
.base = MUSCA_B1_UART1_S_BASE,
.def_baudrate = UART_DEFAULT_BAUD_RATE,
.def_wlen = UART_PL011_WLEN_8,
.def_parity = UART_PL011_PARITY_DISABLED,
.def_stopbit = UART_PL011_STOPBIT_1};
static struct uart_pl011_dev_data_t UART1_PL011_DEV_DATA_S = {
.state = 0,
.uart_clk = 0,
.baudrate = 0};
struct uart_pl011_dev_t UART1_PL011_DEV_S = {&(UART1_PL011_DEV_CFG_S),
&(UART1_PL011_DEV_DATA_S)};
#endif
#ifdef UART1_PL011_NS
static const struct uart_pl011_dev_cfg_t UART1_PL011_DEV_CFG_NS = {
.base = MUSCA_B1_UART1_NS_BASE,
.def_baudrate = UART_DEFAULT_BAUD_RATE,
.def_wlen = UART_PL011_WLEN_8,
.def_parity = UART_PL011_PARITY_DISABLED,
.def_stopbit = UART_PL011_STOPBIT_1};
static struct uart_pl011_dev_data_t UART1_PL011_DEV_DATA_NS = {
.state = 0,
.uart_clk = 0,
.baudrate = 0};
struct uart_pl011_dev_t UART1_PL011_DEV_NS = {&(UART1_PL011_DEV_CFG_NS),
&(UART1_PL011_DEV_DATA_NS)};
#endif
/** CMSDK Timers driver structures */
#ifdef CMSDK_TIMER0_S
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_S = {
.base = MUSCA_B1_CMSDK_TIMER0_S_BASE};
static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_S = {
.is_initialized = 0};
struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S = {&(CMSDK_TIMER0_DEV_CFG_S),
&(CMSDK_TIMER0_DEV_DATA_S)};
#endif
#ifdef CMSDK_TIMER0_NS
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG_NS = {
.base = MUSCA_B1_CMSDK_TIMER0_NS_BASE};
static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA_NS = {
.is_initialized = 0};
struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_NS = {&(CMSDK_TIMER0_DEV_CFG_NS),
&(CMSDK_TIMER0_DEV_DATA_NS)};
#endif
#ifdef CMSDK_TIMER1_S
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG_S = {
.base = MUSCA_B1_CMSDK_TIMER1_S_BASE};
static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA_S = {
.is_initialized = 0};
struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_S = {&(CMSDK_TIMER1_DEV_CFG_S),
&(CMSDK_TIMER1_DEV_DATA_S)};
#endif
#ifdef CMSDK_TIMER1_NS
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG_NS = {
.base = MUSCA_B1_CMSDK_TIMER1_NS_BASE};
static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA_NS = {
.is_initialized = 0};
struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_NS = {&(CMSDK_TIMER1_DEV_CFG_NS),
&(CMSDK_TIMER1_DEV_DATA_NS)};
#endif
/** GFC-100 eflash driver structures */
#ifdef GFC100_EFLASH0_S
static const struct gfc100_eflash_dev_cfg_t GFC100_EFLASH0_CFG_S = {
.base = MUSCA_B1_EFLASH0_REG_MAP_S_BASE};
static struct gfc100_eflash_dev_data_t GFC100_EFLASH0_DATA_S = {
.is_initialized = false,
.flash_size = 0};
struct gfc100_eflash_dev_t GFC100_EFLASH0_DEV_S = {&(GFC100_EFLASH0_CFG_S),
&(GFC100_EFLASH0_DATA_S)};
#endif
#ifdef GFC100_EFLASH1_S
static const struct gfc100_eflash_dev_cfg_t GFC100_EFLASH1_CFG_S = {
.base = MUSCA_B1_EFLASH1_REG_MAP_S_BASE};
static struct gfc100_eflash_dev_data_t GFC100_EFLASH1_DATA_S = {
.is_initialized = false,
.flash_size = 0};
struct gfc100_eflash_dev_t GFC100_EFLASH1_DEV_S = {&(GFC100_EFLASH1_CFG_S),
&(GFC100_EFLASH1_DATA_S)};
#endif
/* General-Purpose Timer driver structures */
#ifdef GP_TIMER_S
static const struct timer_gp_dev_cfg_t GP_TIMER_DEV_CFG_S = {
.base = MUSCA_B1_TIMER_S_BASE};
static struct timer_gp_dev_data_t GP_TIMER_DEV_DATA_S = {
.is_initialized = false,
.alarm0_init = 0,
.alarm1_init = 0};
struct timer_gp_dev_t GP_TIMER_DEV_S = {
&(GP_TIMER_DEV_CFG_S),
&(GP_TIMER_DEV_DATA_S)};
#endif
#ifdef GP_TIMER_NS
static const struct timer_gp_dev_cfg_t GP_TIMER_DEV_CFG_NS = {
.base = MUSCA_B1_TIMER_NS_BASE};
static struct timer_gp_dev_data_t GP_TIMER_DEV_DATA_NS = {
.is_initialized = false,
.alarm0_init = 0,
.alarm1_init = 0};
struct timer_gp_dev_t GP_TIMER_DEV_NS = {
&(GP_TIMER_DEV_CFG_NS),
&(GP_TIMER_DEV_DATA_NS)};
#endif
/* QSPI IP6514E driver structures */
#ifdef QSPI_IP6514E_S
static const struct qspi_ip6514e_dev_cfg_t QSPI_DEV_CFG_S = {
.base = MUSCA_B1_QSPI_REG_S_BASE,
.addr_mask = (1U << 23) - 1, /* 8MiB minus 1 byte */
};
struct qspi_ip6514e_dev_t QSPI_DEV_S = {
&QSPI_DEV_CFG_S
};
#endif
#ifdef QSPI_IP6514E_NS
static const struct qspi_ip6514e_dev_cfg_t QSPI_DEV_CFG_NS = {
.base = MUSCA_B1_QSPI_REG_NS_BASE,
.addr_mask = (1U << 23) - 1, /* 8MiB minus 1 byte */
};
struct qspi_ip6514e_dev_t QSPI_DEV_NS = {
&QSPI_DEV_CFG_NS
};
#endif
/* PL031 Real-Time Clock structure */
#ifdef RTC_PL031_S
static const struct rtc_pl031_dev_cfg_t RTC_PL031_DEV_CFG_S = {
.base = MUSCA_B1_RTC_S_BASE};
struct rtc_pl031_dev_t RTC_PL031_DEV_S = {&(RTC_PL031_DEV_CFG_S)};
#endif
#ifdef RTC_PL031_NS
static const struct rtc_pl031_dev_cfg_t RTC_PL031_DEV_CFG_NS = {
.base = MUSCA_B1_RTC_NS_BASE};
struct rtc_pl031_dev_t RTC_PL031_DEV_NS = {&(RTC_PL031_DEV_CFG_NS)};
#endif
/* I2S IP6718E driver structures */
#ifdef I2S_IP6718E_S
static const struct i2s_ip6718e_dev_cfg_t I2S_IP6718E_DEV_CFG_S = {
.base = MUSCA_B1_I2S_S_BASE,
.audio_intf_mode = I2S_IP6718E_PHILIPS_MODE};
static struct i2s_ip6718e_dev_data_t I2S_IP6718E_DEV_DATA_S = {
.controller_state = 0,
.audio_interface_mode = 0,
.transmitter_audio_frequency = 0,
.receiver_audio_frequency = 0,
.muted = 0};
struct i2s_ip6718e_dev_t I2S_IP6718E_DEV_S = {&(I2S_IP6718E_DEV_CFG_S),
&(I2S_IP6718E_DEV_DATA_S)};
#endif
#ifdef I2S_IP6718E_NS
static const struct i2s_ip6718e_dev_cfg_t I2S_IP6718E_DEV_CFG_NS = {
.base = MUSCA_B1_I2S_NS_BASE,
.audio_intf_mode = I2S_IP6718E_PHILIPS_MODE};
static struct i2s_ip6718e_dev_data_t I2S_IP6718E_DEV_DATA_NS = {
.controller_state = 0,
.audio_interface_mode = 0,
.transmitter_audio_frequency = 0,
.receiver_audio_frequency = 0,
.muted = 0};
struct i2s_ip6718e_dev_t I2S_IP6718E_DEV_NS = {&(I2S_IP6718E_DEV_CFG_NS),
&(I2S_IP6718E_DEV_DATA_NS)};
#endif
/* SSE-200 Cache driver structure */
#ifdef SSE_200_CACHE_S
static const struct arm_cache_dev_cfg_t SSE_200_CACHE_CFG_S = {
.base = MUSCA_B1_CPU_ELEMENT_S_BASE};
struct arm_cache_dev_t SSE_200_CACHE_DEV_S = {&(SSE_200_CACHE_CFG_S)};
#endif
#ifdef SSE_200_CACHE_NS
static const struct arm_cache_dev_cfg_t SSE_200_CACHE_CFG_NS = {
.base = MUSCA_B1_CPU_ELEMENT_NS_BASE};
struct arm_cache_dev_t SSE_200_CACHE_DEV_NS = {&(SSE_200_CACHE_CFG_NS)};
#endif
/* I2C IP6510 driver structures */
#ifdef I2C0_IP6510_S
static const struct i2c_ip6510_dev_cfg_t I2C0_IP6510_DEV_CFG_S = {
.base = MUSCA_B1_I2C0_S_BASE,
.default_mode = I2C_IP6510_MASTER_MODE,
.default_bus_speed = I2C_IP6510_SPEED_100KHZ};
static struct i2c_ip6510_dev_data_t I2C0_IP6510_DEV_DATA_S = {
.state = 0,
.mode = 0,
.bus_speed = 0};
struct i2c_ip6510_dev_t I2C0_IP6510_DEV_S = {
&(I2C0_IP6510_DEV_CFG_S),
&(I2C0_IP6510_DEV_DATA_S)};
#endif
#ifdef I2C0_IP6510_NS
static const struct i2c_ip6510_dev_cfg_t I2C0_IP6510_DEV_CFG_NS = {
.base = MUSCA_B1_I2C0_NS_BASE,
.default_mode = I2C_IP6510_MASTER_MODE,
.default_bus_speed = I2C_IP6510_SPEED_100KHZ};
static struct i2c_ip6510_dev_data_t I2C0_IP6510_DEV_DATA_NS = {
.state = 0,
.mode = 0,
.bus_speed = 0};
struct i2c_ip6510_dev_t I2C0_IP6510_DEV_NS = {
&(I2C0_IP6510_DEV_CFG_NS),
&(I2C0_IP6510_DEV_DATA_NS)};
#endif
#ifdef I2C1_IP6510_S
static const struct i2c_ip6510_dev_cfg_t I2C1_IP6510_DEV_CFG_S = {
.base = MUSCA_B1_I2C1_S_BASE,
.default_mode = I2C_IP6510_MASTER_MODE,
.default_bus_speed = I2C_IP6510_SPEED_100KHZ};
static struct i2c_ip6510_dev_data_t I2C1_IP6510_DEV_DATA_S = {
.state = 0,
.mode = 0,
.bus_speed = 0};
struct i2c_ip6510_dev_t I2C1_IP6510_DEV_S = {
&(I2C1_IP6510_DEV_CFG_S),
&(I2C1_IP6510_DEV_DATA_S)};
#endif
#ifdef I2C1_IP6510_NS
static const struct i2c_ip6510_dev_cfg_t I2C1_IP6510_DEV_CFG_NS = {
.base = MUSCA_B1_I2C1_NS_BASE,
.default_mode = I2C_IP6510_MASTER_MODE,
.default_bus_speed = I2C_IP6510_SPEED_100KHZ};
static struct i2c_ip6510_dev_data_t I2C1_IP6510_DEV_DATA_NS = {
.state = 0,
.mode = 0,
.bus_speed = 0};
struct i2c_ip6510_dev_t I2C1_IP6510_DEV_NS = {
&(I2C1_IP6510_DEV_CFG_NS),
&(I2C1_IP6510_DEV_DATA_NS)};
#endif
/* ======= External peripheral configuration structure definitions ======= */
/* MT25QL Flash memory library structures */
#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S))
struct mt25ql_dev_t MT25QL_DEV_S = {
.controller = &QSPI_DEV_S,
.direct_access_start_addr = MUSCA_B1_QSPI_FLASH_S_BASE,
.baud_rate_div = 4U,
/*
* 8 MiB flash memory are advertised in the Arm Musca-B1 Test Chip and Board
* Technical Reference Manual. The MT25QL Flash device may however contain
* more.
*/
.size = 0x00800000U, /* 8 MiB */
.config_state = { 0 },
};
#endif
#if (defined(MT25QL_NS) && defined(QSPI_IP6514E_NS))
struct mt25ql_dev_t MT25QL_DEV_NS = {
.controller = &QSPI_DEV_NS,
.direct_access_start_addr = MUSCA_B1_QSPI_FLASH_NS_BASE,
.baud_rate_div = 4U,
/*
* 8 MiB flash memory are advertised in the Arm Musca-B1 Test Chip and Board
* Technical Reference Manual. The MT25QL Flash device may however contain
* more.
*/
.size = 0x00800000U, /* 8 MiB */
.config_state = { 0 },
};
#endif

View File

@ -0,0 +1,272 @@
/*
* 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.
*/
/**
* \file device_definition.h
* \brief The structure definitions in this file are exported based on the
* peripheral definitions from device_cfg.h.
* This file is meant to be used as a helper for baremetal
* applications and/or as an example of how to configure the generic
* driver structures.
*/
#ifndef __MUSCA_B1_DEVICE_DEFINITION_H__
#define __MUSCA_B1_DEVICE_DEFINITION_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "device_cfg.h"
/* ======= Peripheral configuration structure declarations ======= */
/* ARM SCC driver structures */
#ifdef MUSCA_B1_SCC_S
#include "musca_b1_scc_drv.h"
extern struct musca_b1_scc_dev_t MUSCA_B1_SCC_DEV_S;
#endif
/* ARM PPC driver structures */
#ifdef AHB_PPC0_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t AHB_PPC0_DEV_S;
#endif
#ifdef AHB_PPCEXP0_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t AHB_PPCEXP0_DEV_S;
#endif
#ifdef AHB_PPCEXP1_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t AHB_PPCEXP1_DEV_S;
#endif
#ifdef AHB_PPCEXP2_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t AHB_PPCEXP2_DEV_S;
#endif
#ifdef AHB_PPCEXP3_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t AHB_PPCEXP3_DEV_S;
#endif
#ifdef APB_PPC0_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPC0_DEV_S;
#endif
#ifdef APB_PPC1_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPC1_DEV_S;
#endif
#ifdef APB_PPCEXP0_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPCEXP0_DEV_S;
#endif
#ifdef APB_PPCEXP1_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPCEXP1_DEV_S;
#endif
#ifdef APB_PPCEXP2_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPCEXP2_DEV_S;
#endif
#ifdef APB_PPCEXP3_S
#include "ppc_sse200_drv.h"
extern struct ppc_sse200_dev_t APB_PPCEXP3_DEV_S;
#endif
/* ARM MPC SIE 200 driver structures */
#ifdef MPC_ISRAM0_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_ISRAM0_DEV_S;
#endif
#ifdef MPC_ISRAM1_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_ISRAM1_DEV_S;
#endif
#ifdef MPC_ISRAM2_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_ISRAM2_DEV_S;
#endif
#ifdef MPC_ISRAM3_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_ISRAM3_DEV_S;
#endif
#ifdef MPC_CODE_SRAM_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_CODE_SRAM_DEV_S;
#endif
#ifdef MPC_QSPI_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_QSPI_DEV_S;
#endif
#ifdef MPC_EFLASH0_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_EFLASH0_DEV_S;
#endif
#ifdef MPC_EFLASH1_S
#include "mpc_sie_drv.h"
extern struct mpc_sie_dev_t MPC_EFLASH1_DEV_S;
#endif
/** CMSDK GPIO driver structures */
#ifdef GPIO0_CMSDK_S
#include "gpio_cmsdk_drv.h"
extern struct gpio_cmsdk_dev_t GPIO0_CMSDK_DEV_S;
#endif
/** CMSDK Timer driver structures */
#ifdef CMSDK_TIMER0_S
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_S;
#endif
#ifdef CMSDK_TIMER0_NS
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV_NS;
#endif
#ifdef CMSDK_TIMER1_S
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_S;
#endif
#ifdef CMSDK_TIMER1_NS
#include "timer_cmsdk_drv.h"
extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV_NS;
#endif
/** ARM UART PL011 driver structures */
#ifdef UART0_PL011_S
#include "uart_pl011_drv.h"
extern struct uart_pl011_dev_t UART0_PL011_DEV_S;
#endif
#ifdef UART0_PL011_NS
#include "uart_pl011_drv.h"
extern struct uart_pl011_dev_t UART0_PL011_DEV_NS;
#endif
#ifdef UART1_PL011_S
#include "uart_pl011_drv.h"
extern struct uart_pl011_dev_t UART1_PL011_DEV_S;
#endif
#ifdef UART1_PL011_NS
#include "uart_pl011_drv.h"
extern struct uart_pl011_dev_t UART1_PL011_DEV_NS;
#endif
#ifdef GFC100_EFLASH0_S
#include "gfc100_eflash_drv.h"
extern struct gfc100_eflash_dev_t GFC100_EFLASH0_DEV_S;
#endif
#ifdef GFC100_EFLASH1_S
#include "gfc100_eflash_drv.h"
extern struct gfc100_eflash_dev_t GFC100_EFLASH1_DEV_S;
#endif
/* General-Purpose Timer driver structures */
#ifdef GP_TIMER_S
#include "timer_gp_drv.h"
extern struct timer_gp_dev_t GP_TIMER_DEV_S;
#endif
#ifdef GP_TIMER_NS
#include "timer_gp_drv.h"
extern struct timer_gp_dev_t GP_TIMER_DEV_NS;
#endif
/* QSPI Flash Controller driver structures */
#ifdef QSPI_IP6514E_S
#include "qspi_ip6514e_drv.h"
extern struct qspi_ip6514e_dev_t QSPI_DEV_S;
#endif
#ifdef QSPI_IP6514E_NS
#include "qspi_ip6514e_drv.h"
extern struct qspi_ip6514e_dev_t QSPI_DEV_NS;
#endif
/* RTC PL031 */
#ifdef RTC_PL031_S
#include "rtc_pl031_drv.h"
extern struct rtc_pl031_dev_t RTC_PL031_DEV_S;
#endif
#ifdef RTC_PL031_NS
#include "rtc_pl031_drv.h"
extern struct rtc_pl031_dev_t RTC_PL031_DEV_NS;
#endif
/* I2S IP6718E driver structures */
#ifdef I2S_IP6718E_S
#include "i2s_ip6718e_drv.h"
extern struct i2s_ip6718e_dev_t I2S_IP6718E_DEV_S;
#endif
#ifdef I2S_IP6718E_NS
#include "i2s_ip6718e_drv.h"
extern struct i2s_ip6718e_dev_t I2S_IP6718E_DEV_NS;
#endif
/* SSE-200 Cache driver structure */
#ifdef SSE_200_CACHE_S
#include "cache_drv.h"
extern struct arm_cache_dev_t SSE_200_CACHE_DEV_S;
#endif
#ifdef SSE_200_CACHE_NS
#include "cache_drv.h"
extern struct arm_cache_dev_t SSE_200_CACHE_DEV_NS;
#endif
/* I2C IP6510 driver structures */
#ifdef I2C0_IP6510_S
#include "i2c_ip6510_drv.h"
extern struct i2c_ip6510_dev_t I2C0_IP6510_DEV_S;
#endif
#ifdef I2C0_IP6510_NS
#include "i2c_ip6510_drv.h"
extern struct i2c_ip6510_dev_t I2C0_IP6510_DEV_NS;
#endif
#ifdef I2C1_IP6510_S
#include "i2c_ip6510_drv.h"
extern struct i2c_ip6510_dev_t I2C1_IP6510_DEV_S;
#endif
#ifdef I2C1_IP6510_NS
#include "i2c_ip6510_drv.h"
extern struct i2c_ip6510_dev_t I2C1_IP6510_DEV_NS;
#endif
/* ======= External peripheral configuration structure declarations ======= */
/* MT25QL Flash memory library structures */
#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S))
#include "mt25ql_flash_lib.h"
extern struct mt25ql_dev_t MT25QL_DEV_S;
#endif
#if (defined(MT25QL_NS) && defined(QSPI_IP6514E_NS))
#include "mt25ql_flash_lib.h"
extern struct mt25ql_dev_t MT25QL_DEV_NS;
#endif
#ifdef __cplusplus
}
#endif
#endif /* __MUSCA_B1_DEVICE_DEFINITION_H__ */

View File

@ -0,0 +1,324 @@
/*
* 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.
*/
#include <stdint.h>
#include <stddef.h>
#include "gpio_cmsdk_drv.h"
/* GPIO register map structure */
struct gpio_cmsdk_reg_map_t {
volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */
volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output
* latch register */
volatile uint32_t reserved0[2];
volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable
* set register */
volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable
* clear register */
volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function
* set register */
volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function
* clear register */
volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable
* set register */
volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable
* clear register */
volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type
* set register */
volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type
* clear register */
volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity
* set register */
volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity
* clear register */
union {
volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status
* register */
volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear
* register */
}intreg;
volatile uint32_t reserved1[997];
volatile uint32_t pid4; /* Peripheral ID Register 4 */
volatile uint32_t pid0; /* Peripheral ID Register 0 */
volatile uint32_t pid1; /* Peripheral ID Register 1 */
volatile uint32_t pid2; /* Peripheral ID Register 2 */
volatile uint32_t pid3; /* Peripheral ID Register 3 */
volatile uint32_t cid0; /* Component ID Register 0 */
volatile uint32_t cid1; /* Component ID Register 1 */
volatile uint32_t cid2; /* Component ID Register 2 */
volatile uint32_t cid4; /* Component ID Register 3 */
};
void gpio_cmsdk_init(struct gpio_cmsdk_dev_t* dev)
{
/* Nothing to init on the GPIO device */
}
/**
* \brief Configures port.
*
* \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Pin mask for port access
* \param[in] direction Input or output \ref gpio_cmsdk_direction_t
* \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
*
*/
static void set_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_direction_t direction,
enum gpio_cmsdk_altfunc_t altfunc_flags)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(direction == GPIO_CMSDK_INPUT) {
p_gpio_port->outenableclr = pin_mask;
} else {
p_gpio_port->outenableset = pin_mask;
}
if (altfunc_flags == GPIO_CMSDK_MAIN_FUNC) {
p_gpio_port->altfuncclr = pin_mask;
} else {
p_gpio_port->altfuncset = pin_mask;
}
return;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_pin_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
enum gpio_cmsdk_direction_t direction,
enum gpio_cmsdk_altfunc_t altfunc_flags)
{
uint32_t pin_mask = (1UL << pin_num);
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
set_port_config(dev, pin_mask, direction, altfunc_flags);
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_direction_t direction,
enum gpio_cmsdk_altfunc_t altfunc_flags)
{
if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
set_port_config(dev, pin_mask, direction, altfunc_flags);
return GPIO_CMSDK_ERR_NONE;
}
void gpio_cmsdk_config_irq(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_irq_type_t irq_type,
enum gpio_cmsdk_irq_polarity_t irq_pol)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
/* Interrupt type: EDGE = 1 - LEVEL = 0 */
if(irq_type == GPIO_CMSDK_IRQ_EDGE) {
p_gpio_port->inttypeset = pin_mask;
} else if(irq_type == GPIO_CMSDK_IRQ_LEVEL) {
p_gpio_port->inttypeclr = pin_mask;
}
/* Interrupt polarity */
if(irq_pol == GPIO_CMSDK_IRQ_LOW_OR_FALLING_EDGE) {
p_gpio_port->intpolclr = pin_mask;
} else if(irq_pol == GPIO_CMSDK_IRQ_HIGH_OR_RISING_EDGE) {
p_gpio_port->intpolset = pin_mask;
}
}
enum gpio_cmsdk_error_t gpio_cmsdk_pin_write(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_num,
uint32_t value)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
/* GPIO data output register is a read-modify-write register,
* so before writing a value on a GPIO pin it is required to disable
* the interrupts to prevent concurrency problems.
*/
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
if(value) {
/* Sets the pin */
p_gpio_port->dataout |= (1UL << pin_num);
} else {
/* Clears the pin */
p_gpio_port->dataout &= ~(1UL << pin_num);
}
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t gpio_cmsdk_port_write(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_mask,
uint32_t value)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
/* GPIO data output register is a read-modify-write register,
* so before writing a value on a GPIO pin it is required to disable
* the interrupts to prevent concurrency problems.
*/
if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
/* Clear all bits defined in the mask,
* and set selected bits from value parameter.
*/
p_gpio_port->dataout =
((~pin_mask & p_gpio_port->dataout) | (pin_mask & value));
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_pin_read(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_num,
uint32_t *data)
{
uint32_t value;
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
value = p_gpio_port->data;
*data = (value >> pin_num) & 1UL;
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_port_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
uint32_t *data)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
*data = p_gpio_port->data & pin_mask;
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_set_pin_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
enum gpio_cmsdk_irq_status_t status)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
if(status == GPIO_CMSDK_IRQ_ENABLE) {
p_gpio_port->intenset = (1UL << pin_num);
} else {
p_gpio_port->intenclr = (1UL << pin_num);
}
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_set_port_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_irq_status_t status)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
if(status == GPIO_CMSDK_IRQ_ENABLE) {
p_gpio_port->intenset = pin_mask;
} else {
p_gpio_port->intenclr = pin_mask;
}
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_get_pin_irq_status(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_num, uint32_t* status)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
*status = ((p_gpio_port->intreg.intstatus >> pin_num) & 1UL);
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t
gpio_cmsdk_get_port_irq_status(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_mask, uint32_t* status)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_mask > GPIO_CMSDK_MAX_PORT_MASK) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
*status = (p_gpio_port->intreg.intstatus & pin_mask);
return GPIO_CMSDK_ERR_NONE;
}
enum gpio_cmsdk_error_t gpio_cmsdk_clear_irq(struct gpio_cmsdk_dev_t* dev,
uint8_t pin_num)
{
struct gpio_cmsdk_reg_map_t* p_gpio_port =
(struct gpio_cmsdk_reg_map_t*)dev->cfg->base;
if(pin_num >= GPIO_CMSDK_MAX_PIN_NUM) {
return GPIO_CMSDK_ERR_INVALID_ARG;
}
p_gpio_port->intreg.intclear = (1UL << pin_num);
return GPIO_CMSDK_ERR_NONE;
}

View File

@ -0,0 +1,279 @@
/*
* 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.
*/
/**
* \file gpio_cmsdk_drv.h
* \brief Generic driver for ARM GPIO.
*/
#ifndef __GPIO_CMSDK_DRV_H__
#define __GPIO_CMSDK_DRV_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GPIO_CMSDK_MAX_PIN_NUM 16U
#define GPIO_CMSDK_MAX_PORT_MASK ((1U << GPIO_CMSDK_MAX_PIN_NUM) - 1U)
/* GPIO enumeration types */
enum gpio_cmsdk_direction_t {
GPIO_CMSDK_INPUT = 0, /*!< GPIO is input */
GPIO_CMSDK_OUTPUT /*!< GPIO is output */
};
enum gpio_cmsdk_altfunc_t {
GPIO_CMSDK_MAIN_FUNC = 0, /*!< Alternate function is not enabled */
GPIO_CMSDK_ALT_FUNC /*!< Alternate function is enabled */
};
enum gpio_cmsdk_irq_status_t {
GPIO_CMSDK_IRQ_DISABLE = 0, /*!< Disable interruptions */
GPIO_CMSDK_IRQ_ENABLE /*!< Enable interruptions */
};
enum gpio_cmsdk_irq_type_t {
GPIO_CMSDK_IRQ_LEVEL = 0, /*!< Level Interrupt */
GPIO_CMSDK_IRQ_EDGE /*!< Edge Interrupt */
};
enum gpio_cmsdk_irq_polarity_t {
GPIO_CMSDK_IRQ_LOW_OR_FALLING_EDGE = 0, /*!< Interrupt active low or
falling edge */
GPIO_CMSDK_IRQ_HIGH_OR_RISING_EDGE /*!< Interrupt active high or
rising edge */
};
enum gpio_cmsdk_error_t {
GPIO_CMSDK_ERR_NONE = 0, /*!< No error */
GPIO_CMSDK_ERR_INVALID_ARG, /*!< Error invalid input argument */
GPIO_CMSDK_ALTFUNC_EERROR, /*!< Alternate function returned error */
};
/* CMSDK GPIO device configuration structure */
struct gpio_cmsdk_dev_cfg_t {
const uint32_t base; /*!< GPIO base address */
};
/* CMSDK GPIO device structure */
struct gpio_cmsdk_dev_t {
const struct gpio_cmsdk_dev_cfg_t* const cfg; /*!< GPIO configuration */
};
/**
* \brief Initializes GPIO port.
*
* \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
*
* \note This function doesn't check if dev is NULL.
*/
void gpio_cmsdk_init(struct gpio_cmsdk_dev_t* dev);
/**
* \brief Configures pin.
*
* \param[in] dev GPIO device to configure \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number for pin access
* \param[in] direction Input or output \ref gpio_cmsdk_direction_t
* \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
*
* \return Returns error code as specified in \ref gpio_cmsdk_flags_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_pin_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
enum gpio_cmsdk_direction_t direction,
enum gpio_cmsdk_altfunc_t altfunc_flags);
/**
* \brief Configures port.
*
* \param[in] dev GPIO device to configure \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the selected pins
* \param[in] direction Input or output \ref gpio_cmsdk_direction_t
* \param[in] altfunc_flags Alternate function \ref gpio_cmsdk_altfunc_t
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_port_config(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_direction_t direction,
enum gpio_cmsdk_altfunc_t altfunc_flags);
/**
* \brief Configures interrupt type
*
* \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the selected pins
* \param[in] irq_type Interrupt type \ref gpio_cmsdk_irq_type_t
* \param[in] irq_pol Interrupt polarity \ref gpio_cmsdk_irq_polarity_t
*
* \note This function doesn't check if dev is NULL.
*/
void gpio_cmsdk_config_irq(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_irq_type_t irq_type,
enum gpio_cmsdk_irq_polarity_t irq_pol);
/**
* \brief Sets state of the output pin.
*
* \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number for pin access
* \param[in] value Value(s) to set.
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
* \note GPIO data output register is a read-modify-write register,
* so before writing a value on a GPIO pin it is required to disable
* the interrupts to prevent concurrency problems.
*/
enum gpio_cmsdk_error_t gpio_cmsdk_pin_write(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_num,
uint32_t value);
/**
* \brief Sets state of the output port.
*
* \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the selected pins
* \param[in] value Bitmask of pins states to set
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
* \note GPIO data output register is a read-modify-write register,
* so before writing a value on a GPIO pin it is required to disable
* the interrupts to prevent concurrency problems.
*/
enum gpio_cmsdk_error_t gpio_cmsdk_port_write(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_mask,
uint32_t value);
/**
* \brief Reads the pin status.
*
* \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number for pin access
* \param[out] data Bit value read from the IO pin
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_pin_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num, uint32_t *data);
/**
* \brief Reads the port status.
*
* \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the selected pins
* \param[out] data Bit values for the mask read from the IO pin
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_port_read(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
uint32_t *data);
/**
* \brief Enables/disables interrupt for the given pin.
*
* \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number to configure
* \param[in] status Interrupt status \ref gpio_cmsdk_irq_status
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_set_pin_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_num,
enum gpio_cmsdk_irq_status_t status);
/**
* \brief Enables/disables interrupt for the given pins.
*
* \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the pins to configure
* \param[in] status Interrupt status \ref gpio_cmsdk_irq_status
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_set_port_irq_cfg(struct gpio_cmsdk_dev_t* dev, uint32_t pin_mask,
enum gpio_cmsdk_irq_status_t status);
/**
* \brief Get interrupt status for the given pin.
*
* \param[in] dev GPIO device to use for the pin \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number for the access
* \param[out] status Interrupt status values. If the access is by pin, then
* the status will be 0 or 1.
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_get_pin_irq_status(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_num, uint32_t* status);
/**
* \brief Get interrupt status for the given port.
*
* \param[in] dev GPIO device to use for the pins \ref gpio_cmsdk_dev_t
* \param[in] pin_mask Bitmask of the pins to configure
* \param[out] status Interrupt status values. If the access is by pin,
* then the status will be 0 or 1.
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t
gpio_cmsdk_get_port_irq_status(struct gpio_cmsdk_dev_t* dev,
uint32_t pin_mask, uint32_t* status);
/**
* \brief Clears gpio interrupt.
*
* \param[in] dev GPIO device to initalize \ref gpio_cmsdk_dev_t
* \param[in] pin_num Pin number.
*
* \return Returns error code as specified in \ref gpio_cmsdk_error_t
*
* \note This function doesn't check if dev is NULL.
*/
enum gpio_cmsdk_error_t gpio_cmsdk_clear_irq(struct gpio_cmsdk_dev_t* dev,
uint8_t pin_num);
#ifdef __cplusplus
}
#endif
#endif /* __GPIO_CMSDK_DRV_H__ */

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 2018-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 "musca_b1_scc_drv.h"
/* The first pin of the upper pins (out of 64) */
#define GPIO_UPPER_PINS_MIN_VALUE 32U
struct musca_b1_scc_reg_map_t {
volatile uint32_t clk_ctrl_sel; /* 0x00 RW Clock Control Select */
volatile uint32_t clk_pll_prediv_ctrl; /* 0x04 RW clk_pll_prediv_ctrl */
volatile uint32_t reserved1; /* 0x08 Reserved */
volatile uint32_t clk_postdiv_ctrl_flash; /* 0x0C RW clk_postdiv_ctrl_flash */
volatile uint32_t clk_postdiv_qspi; /* 0x10 RW clk_postdiv_qspi */
volatile uint32_t clk_postdiv_rtc; /* 0x14 RW clk_postdiv_rtc */
volatile uint32_t clk_postdiv_sd; /* 0x18 RW clk_postdiv_sd */
volatile uint32_t clk_postdiv_test; /* 0x1C RW clk_postdiv_test */
volatile uint32_t ctrl_bypass_div; /* 0x20 RW ctrl_bypass_div */
volatile uint32_t pll_ctrl_pll0_clk; /* 0x24 RW pll_ctrl_pll0_clk */
volatile uint32_t pll_postdiv_ctrl_pll0_clk; /* 0x28 RW pll_postdiv_ctrl_pll0_clk */
volatile uint32_t pll_ctrl_mult_pll0_clk; /* 0x2C RW pll_ctrl_mult_pll0_clk */
volatile uint32_t clk_ctrl_enable; /* 0x30 RW Clock Control Enable */
volatile uint32_t clk_status; /* 0x34 RO Clock Status */
volatile uint32_t reserved2[2]; /* 0x38 Reserved */
volatile uint32_t reset_ctrl; /* 0x40 RW Reset Control Register */
volatile uint32_t reserved3; /* 0x44 Reserved */
volatile uint32_t dbg_ctrl; /* 0x48 RW Debug Control Register */
volatile uint32_t sram_ctrl; /* 0x4C RW SRAM Control Register */
volatile uint32_t intr_ctrl; /* 0x50 RW Interupt Control Register */
volatile uint32_t clk_test_ctrl; /* 0x54 RW Clock Test Control Register */
volatile uint32_t cpu0_vtor; /* 0x58 RW Reset vector for CPU0 */
volatile uint32_t reserved4; /* 0x5C RW Reset vector for KX CPU */
volatile uint32_t cpu1_vtor; /* 0x60 Reserved */
volatile uint32_t az_cpu_vtor; /* 0x64 RW Reset vector for AZ CPU */
volatile uint32_t iomux_main_insel_0; /* 0x68 RW Main function in data select */
volatile uint32_t iomux_main_insel_1; /* 0x6C RW Main function in data select */
volatile uint32_t iomux_main_outsel_0; /* 0x70 RW Main function out data select */
volatile uint32_t iomux_main_outsel_1; /* 0x74 RW Main function out data select */
volatile uint32_t iomux_main_oensel_0; /* 0x78 RW Main function out enable select */
volatile uint32_t iomux_main_oensel_1; /* 0x7C RW Main function out enable select */
volatile uint32_t iomux_main_default_in_0; /* 0x80 RW Main function default in select */
volatile uint32_t iomux_main_default_in_1; /* 0x84 RW Main function default in select */
volatile uint32_t iomux_altf1_insel_0; /* 0x88 RW Alt function 1 in data select */
volatile uint32_t iomux_altf1_insel_1; /* 0x8C RW Alt function 1 in data select */
volatile uint32_t iomux_altf1_outsel_0; /* 0x90 RW Alt function 1 out data select */
volatile uint32_t iomux_altf1_outsel_1; /* 0x94 RW Alt function 1 out data select */
volatile uint32_t iomux_altf1_oensel_0; /* 0x98 RW Alt function 1 out enable select */
volatile uint32_t iomux_altf1_oensel_1; /* 0x9C RW Alt function 1 out enable select */
volatile uint32_t iomux_altf1_default_in_0; /* 0xA0 RW Alt function 1 default in select */
volatile uint32_t iomux_altf1_default_in_1; /* 0xA4 RW Alt function 1 default in select */
volatile uint32_t iomux_altf2_insel_0; /* 0xA8 RW Alt function 2 in data select */
volatile uint32_t iomux_altf2_insel_1; /* 0xAC RW Alt function 2 in data select */
volatile uint32_t iomux_altf2_outsel_0; /* 0xB0 RW Alt function 2 out data select */
volatile uint32_t iomux_altf2_outsel_1; /* 0xB4 RW Alt function 2 out data select */
volatile uint32_t iomux_altf2_oensel_0; /* 0xB8 RW Alt function 2 out enable select */
volatile uint32_t iomux_altf2_oensel_1; /* 0xBC RW Alt function 2 out enable select */
volatile uint32_t iomux_altf2_default_in_0; /* 0xC0 RW Alt function 2 default in select */
volatile uint32_t iomux_altf2_default_in_1; /* 0xC4 RW Alt function 2 default in select */
volatile uint32_t reserved5[8]; /* 0xC8 Reserved */
volatile uint32_t iopad_ds0_0; /* 0xE8 RW Drive Select 0 */
volatile uint32_t iopad_ds0_1; /* 0xEC RW Drive Select 0 */
volatile uint32_t iopad_ds1_0; /* 0xF0 RW Drive Select 1 */
volatile uint32_t iopad_ds1_1; /* 0xF4 RW Drive Select 1 */
volatile uint32_t iopad_pe_0; /* 0xF8 RW Pull Enable */
volatile uint32_t iopad_pe_1; /* 0xFC RW Pull Enable */
volatile uint32_t iopad_ps_0; /* 0x100 RW Pull Select */
volatile uint32_t iopad_ps_1; /* 0x104 RW Pull Select */
volatile uint32_t iopad_sr_0; /* 0x108 RW Slew Select */
volatile uint32_t iopad_sr_1; /* 0x10C RW Slew Select */
volatile uint32_t iopad_is_0; /* 0x110 RW Input Select */
volatile uint32_t iopad_is_1; /* 0x114 RW Input Select */
volatile uint32_t pvt_ctrl; /* 0x118 RW PVT control register */
volatile uint32_t reserved6[5]; /* 0x11C Reserved */
volatile uint32_t spare0; /* 0x130 RW spare0 */
volatile uint32_t reserved7[2]; /* 0x134 Reserved */
volatile uint32_t static_conf_sig1; /* 0x13C RW static_conf_sig1 */
volatile uint32_t reserved8[24]; /* 0x140 Reserved */
volatile uint32_t flash0_din_0; /* 0x1A0 RW flash0_or 1 din_0 */
volatile uint32_t flash0_din_1; /* 0x1A4 RW flash0 or 1 din_1 */
volatile uint32_t flash0_din_2; /* 0x1A8 RW flash0_or 1 din_2 */
volatile uint32_t flash0_din_3; /* 0x1AC RW flash0_or 1 din_3 */
volatile uint32_t reserved9[4]; /* 0x1B0 Reserved */
volatile uint32_t flash0_dout_0; /* 0x1C0 RO flash0_dout_0 */
volatile uint32_t flash0_dout_1; /* 0x1C4 RO flash0_dout_1 */
volatile uint32_t flash0_dout_2; /* 0x1C8 RO flash0_dout_2 */
volatile uint32_t flash0_dout_3; /* 0x1CC RO flash0_dout_3 */
volatile uint32_t flash1_dout_0; /* 0x1D0 RO flash1_dout_0 */
volatile uint32_t flash1_dout_1; /* 0x1D4 RO flash1_dout_1 */
volatile uint32_t flash1_dout_2; /* 0x1D8 RO flash1_dout_2 */
volatile uint32_t flash1_dout_3; /* 0x1DC RO flash1_dout_2 */
volatile uint32_t selection_control_reg; /* 0x1E0 RW Selection Control Register */
volatile uint32_t az_rom_remap_mask; /* 0x1E4 RW az_rom_remap_mask */
volatile uint32_t az_rom_remap_offset; /* 0x1E8 RW az_rom_remap_offset */
volatile uint32_t az_code_remap_mask; /* 0x1EC RW az_code_remap_mask */
volatile uint32_t az_code_remap_offset; /* 0x1F0 RW az_code_remap_offset */
volatile uint32_t az_sys_remap_mask; /* 0x1F4 RW az_sys_remap_mask */
volatile uint32_t az_sys_remap_offset; /* 0x1F8 RW az_sys_remap_offset */
volatile uint32_t reserved10; /* 0x1FC RW Kalix Control */
volatile uint32_t az_ctrl; /* 0x200 RW Alcatraz Control */
volatile uint32_t reserved11; /* 0x204 Reserved */
volatile uint32_t sse200_otp_rd_data; /* 0x208 RO SSE200_otp_ctrl */
volatile uint32_t reserved12; /* 0x20C Reserved */
volatile uint32_t az_otp_rd_data; /* 0x210 RO az_otp_rd_data */
volatile uint32_t reserved13[2]; /* 0x214 Reserved */
volatile uint32_t spare_ctrl0; /* 0x21C RW spare_ctrl0 */
volatile uint32_t spare_ctrl1; /* 0x220 RW spare_ctrl1 */
volatile uint32_t reserved[119]; /* 0x224 Reserved */
volatile uint32_t chip_id; /* 0x400 RO Chip ID 0x07D00477 */
};
/**
* \brief Clears selected alternate functions for selected pins
*
* \param[in] scc_regs SCC register map pointer \ref musca_b1_scc_reg_map_t
* \param[in] func_mask Bitmask of alternate functions to clear
* \ref gpio_altfunc_mask_t
* \param[in] pin_mask Pin mask for the alternate functions
* \param[in] upper_pins True if pin_mask represents the upper 32 pins
*/
static void scc_clear_alt_func(struct musca_b1_scc_reg_map_t* scc_regs,
enum gpio_altfunc_mask_t func_mask,
uint32_t pin_mask, bool upper_pins)
{
/* The pin select pointers are pointing to the registers
* which control the lower 32 pins of the whole 64. If we need to reach
* the upper 32 pins, the pointers need to be incremented.
* Registers are 32 bites wide so offset is in 4 byte steps.
*/
uint32_t reg_offset = (upper_pins ? 1U : 0U);
if (func_mask & GPIO_MAIN_FUNC_MASK) {
*(&scc_regs->iomux_main_insel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_main_outsel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_main_oensel_0 + reg_offset) &= (~pin_mask);
}
if (func_mask & GPIO_ALTFUNC_1_MASK) {
*(&scc_regs->iomux_altf1_insel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_altf1_outsel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_altf1_oensel_0 + reg_offset) &= (~pin_mask);
}
if (func_mask & GPIO_ALTFUNC_2_MASK) {
*(&scc_regs->iomux_altf2_insel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_altf2_outsel_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iomux_altf2_oensel_0 + reg_offset) &= (~pin_mask);
}
}
/**
* \brief Sets selected alternate functions for selected (max 32) pins
*
* \param[in] scc_regs SCC register map pointer \ref musca_b1_scc_reg_map_t
* \param[in] altfunc Alternate function to set \ref gpio_altfunc_t
* \param[in] pin_mask Pin mask for the alternate functions
* \param[in] upper_pins True if pin_mask represents the upper 32 pins
*
* \note This function doesn't check if scc dev is NULL.
* \note If no alternate function is selected then this API won't do anything
*/
static void scc_set_alt_func(struct musca_b1_scc_reg_map_t* scc_regs,
enum gpio_altfunc_t altfunc, uint32_t pin_mask,
bool upper_pins)
{
enum gpio_altfunc_mask_t altfunc_to_clear = GPIO_ALTFUNC_NONE;
volatile uint32_t *insel = NULL;
volatile uint32_t *outse = NULL;
volatile uint32_t *oense = NULL;
switch (altfunc) {
case GPIO_MAIN_FUNC:
insel = &scc_regs->iomux_main_insel_0;
outse = &scc_regs->iomux_main_outsel_0;
oense = &scc_regs->iomux_main_oensel_0;
altfunc_to_clear = GPIO_MAIN_FUNC_NEG_MASK;
break;
case GPIO_ALTFUNC_1:
insel = &scc_regs->iomux_altf1_insel_0;
outse = &scc_regs->iomux_altf1_outsel_0;
oense = &scc_regs->iomux_altf1_oensel_0;
altfunc_to_clear = GPIO_ALTFUNC_1_NEG_MASK;
break;
case GPIO_ALTFUNC_2:
insel = &scc_regs->iomux_altf2_insel_0;
outse = &scc_regs->iomux_altf2_outsel_0;
oense = &scc_regs->iomux_altf2_oensel_0;
altfunc_to_clear = GPIO_ALTFUNC_2_NEG_MASK;
break;
case GPIO_ALTFUNC_3:
/* Nothing to do, clearing the other functions enables ALTFUNC 3 */
altfunc_to_clear = GPIO_ALTFUNC_3_NEG_MASK;
scc_clear_alt_func(scc_regs, altfunc_to_clear, pin_mask, upper_pins);
return;
default:
return;
}
if (upper_pins == true) {
/* All the pin select pointers are pointing to the registers
* which control the lower 32 pins of the whole 64. If we need to reach
* the upper 32 pins, the pointers need to be incremented.
*/
insel++;
outse++;
oense++;
}
/* Select the wanted function's output enable bit first.
* This way the output won't be disabled which is desired
* if we switch from output to output function
*/
*oense |= pin_mask;
/* Clear all alternate function registers which are not selected */
scc_clear_alt_func(scc_regs, altfunc_to_clear, pin_mask, upper_pins);
/* Enable input and output data line */
*insel |= pin_mask;
*outse |= pin_mask;
}
enum musca_b1_scc_error_t
musca_b1_scc_set_alt_func(struct musca_b1_scc_dev_t* dev,
enum gpio_altfunc_t altfunc, uint64_t pin_mask)
{
struct musca_b1_scc_reg_map_t* scc_regs =
(struct musca_b1_scc_reg_map_t*) dev->cfg->base;
uint32_t pin_mask_lo = (uint32_t)pin_mask;
uint32_t pin_mask_hi = (uint32_t)(pin_mask >> GPIO_UPPER_PINS_MIN_VALUE);
if (altfunc >= GPIO_ALTFUNC_MAX) {
/* Invalid input */
return SCC_INVALID_ARG;
}
/* Set alternate functions for the lower 32 pins - if needed */
if (pin_mask_lo != 0U) {
scc_set_alt_func(scc_regs, altfunc, pin_mask_lo, false);
}
/* Set alternate functions for the upper 32 pins - if needed */
if (pin_mask_hi != 0U) {
scc_set_alt_func(scc_regs, altfunc, pin_mask_hi, true);
}
return SCC_ERR_NONE;
}
/**
* \brief Sets pinmode for the given pins
*
* \param[in] scc_regs SCC register map pointer \ref musca_b1_scc_reg_map_t
* \param[in] pin_mask Pin mask for the alternate functions
* \param[in] mode Pin mode to set \ref pinmode_select_t
* \param[in] upper_pins True if the pinmask is for the upper 32 pins,
* false otherwise
*/
static void scc_set_pinmode(struct musca_b1_scc_reg_map_t* scc_regs,
uint32_t pin_mask,
enum pinmode_select_t mode, bool upper_pins)
{
/* The pin select pointers are pointing to the registers
* which control the lower 32 pins of the whole 64. If we need to reach
* the upper 32 pins, the pointers need to be incremented.
* Registers are 32 bites wide so offset is in 4 byte steps.
*/
uint32_t reg_offset = (upper_pins ? 1U : 0U);
switch (mode) {
case PINMODE_NONE:
*(&scc_regs->iopad_pe_0 + reg_offset) &= (~pin_mask);
break;
case PINMODE_PULL_DOWN:
/* If the pull select bit is set to 0 it means pull down */
*(&scc_regs->iopad_ps_0 + reg_offset) &= (~pin_mask);
*(&scc_regs->iopad_pe_0 + reg_offset) |= pin_mask;
break;
case PINMODE_PULL_UP:
/* If the pull select bit is set to 1 it means pull up */
*(&scc_regs->iopad_ps_0 + reg_offset) |= pin_mask;
*(&scc_regs->iopad_pe_0 + reg_offset) |= pin_mask;
break;
default:
break;
}
}
enum musca_b1_scc_error_t
musca_b1_scc_set_pinmode(struct musca_b1_scc_dev_t* dev, uint64_t pin_mask,
enum pinmode_select_t mode)
{
struct musca_b1_scc_reg_map_t* scc_regs =
(struct musca_b1_scc_reg_map_t*) dev->cfg->base;
uint32_t pin_mask_lo = (uint32_t)pin_mask;
uint32_t pin_mask_hi = (uint32_t)(pin_mask >> 32);
if (mode >= PINMODE_MAX) {
/* Invalid input */
return SCC_INVALID_ARG;
}
/* Set pin mode for the lower 32 pins - if needed */
if (pin_mask_lo != 0U) {
scc_set_pinmode(scc_regs, pin_mask_lo, mode, false);
}
/* Set pin mode for the lower 32 pins - if needed */
if (pin_mask_hi != 0U) {
scc_set_pinmode(scc_regs, pin_mask_hi, mode, true);
}
return SCC_ERR_NONE;
}
enum musca_b1_scc_error_t
musca_b1_scc_set_default_in(struct musca_b1_scc_dev_t* dev,
enum gpio_altfunc_t altfunc,
uint32_t pin_num,
bool default_in_value)
{
struct musca_b1_scc_reg_map_t* scc_regs =
(struct musca_b1_scc_reg_map_t*) dev->cfg->base;
uint32_t iomux_value = 0U;
uint32_t pin_mask = 0U;
uint32_t default_in_mask = 0U;
uint32_t reg_offset = 0U;
if ((altfunc >= GPIO_ALTFUNC_MAX) || (pin_num >= GPIO_ALTFUNC_MAX_PINS)) {
/* Invalid input */
return SCC_INVALID_ARG;
}
/* Check if pin is the upper section */
if (pin_num >= GPIO_UPPER_PINS_MIN_VALUE) {
pin_num -= GPIO_UPPER_PINS_MIN_VALUE;
/* The pin select pointers are pointing to the registers
* which control the lower 32 pins of the whole 64. If we need
* to reach the upper 32 pins, the pointers need to be incremented.
* Registers are 32 bites wide so offset is in 4 byte steps.
*/
reg_offset = 1U;
}
pin_mask = (1U << pin_num);
default_in_mask = ((default_in_value ? 1U : 0U) << pin_num);
switch (altfunc) {
case GPIO_MAIN_FUNC:
iomux_value =
*(&scc_regs->iomux_main_default_in_0 + reg_offset) & (~pin_mask);
*(&scc_regs->iomux_main_default_in_0 + reg_offset) =
(iomux_value | default_in_mask);
*(&scc_regs->iomux_main_insel_0 + reg_offset) =
(*(&scc_regs->iomux_main_insel_0 + reg_offset) & (~pin_mask));
break;
case GPIO_ALTFUNC_1:
iomux_value =
*(&scc_regs->iomux_altf1_default_in_0 + reg_offset) & (~pin_mask);
*(&scc_regs->iomux_altf1_default_in_0 + reg_offset) =
(iomux_value | default_in_mask);
*(&scc_regs->iomux_altf1_insel_0 + reg_offset) =
(*(&scc_regs->iomux_altf1_insel_0 + reg_offset) & (~pin_mask));
break;
case GPIO_ALTFUNC_2:
iomux_value =
*(&scc_regs->iomux_altf2_default_in_0 + reg_offset) & (~pin_mask);
*(&scc_regs->iomux_altf2_default_in_0 + reg_offset) =
(iomux_value | default_in_mask);
*(&scc_regs->iomux_altf2_insel_0 + reg_offset) =
(*(&scc_regs->iomux_altf2_insel_0 + reg_offset) & (~pin_mask));
break;
case GPIO_ALTFUNC_3:
/* Reserved */
break;
default:
/* Code should already returned error but just to be safe
* return here as well
*/
return SCC_INVALID_ARG;
}
return SCC_ERR_NONE;
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2018-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.
*/
#ifndef __MUSCA_B1_SCC_DRV_H__
#define __MUSCA_B1_SCC_DRV_H__
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** 38 pins can be controlled in total - including the reserved ones */
#define GPIO_ALTFUNC_MAX_PINS 38U
/** Allowed error codes. */
enum musca_b1_scc_error_t {
SCC_ERR_NONE = 0U,
SCC_INVALID_ARG
};
/**
* Enum to store alternate function values.
* They are used as shift operand, must be unsigned.
*/
enum gpio_altfunc_t {
GPIO_MAIN_FUNC = 0UL,
GPIO_ALTFUNC_1,
GPIO_ALTFUNC_2,
GPIO_ALTFUNC_3,
GPIO_ALTFUNC_MAX
};
#define GPIO_ALTFUNC_ALL_MASK ((1U << GPIO_ALTFUNC_MAX) - 1)
/** Enum to store alternate function mask values.*/
enum gpio_altfunc_mask_t {
GPIO_ALTFUNC_NONE = 0,
GPIO_MAIN_FUNC_MASK = (1UL << GPIO_MAIN_FUNC),
GPIO_ALTFUNC_1_MASK = (1UL << GPIO_ALTFUNC_1),
GPIO_ALTFUNC_2_MASK = (1UL << GPIO_ALTFUNC_2),
GPIO_ALTFUNC_3_MASK = (1UL << GPIO_ALTFUNC_3),
GPIO_MAIN_FUNC_NEG_MASK = (~GPIO_MAIN_FUNC_MASK & GPIO_ALTFUNC_ALL_MASK),
GPIO_ALTFUNC_1_NEG_MASK = (~GPIO_ALTFUNC_1_MASK & GPIO_ALTFUNC_ALL_MASK),
GPIO_ALTFUNC_2_NEG_MASK = (~GPIO_ALTFUNC_2_MASK & GPIO_ALTFUNC_ALL_MASK),
GPIO_ALTFUNC_3_NEG_MASK = (~GPIO_ALTFUNC_3_MASK & GPIO_ALTFUNC_ALL_MASK)
};
/** Supported pin modes */
enum pinmode_select_t {
PINMODE_NONE = 0U,
PINMODE_PULL_DOWN,
PINMODE_PULL_UP,
PINMODE_MAX
};
/** Musca SCC device configuration structure */
struct musca_b1_scc_dev_cfg_t {
const uint32_t base; /*!< SCC base address */
};
/** Musca SCC device structure */
struct musca_b1_scc_dev_t {
const struct musca_b1_scc_dev_cfg_t* const cfg; /*!< SCC configuration */
};
/**
* \brief Sets selected alternate functions for selected pins
*
* \param[in] dev SCC device pointer \ref musca_b1_scc_dev_t
* \param[in] altfunc Alternate function to set \ref gpio_altfunc_t
* \param[in] pin_mask Pin mask for the alternate functions
*
* \return Returns error code. \ref musca_b1_scc_error_t
*
* \note This function doesn't check if scc dev is NULL.
* \note If no alternate function is selected then this API won't do anything
*/
enum musca_b1_scc_error_t
musca_b1_scc_set_alt_func(struct musca_b1_scc_dev_t* dev,
enum gpio_altfunc_t altfunc, uint64_t pin_mask);
/**
* \brief Sets pinmode for the given pins
*
* \param[in] dev SCC device pointer \ref musca_b1_scc_dev_t
* \param[in] pin_mask Pin mask for the alternate functions
* \param[in] mode Pin mode to set \ref pinmode_select_t
*
* \return Returns error code. \ref musca_b1_scc_error_t
*
* \note This function doesn't check if scc dev is NULL.
*/
enum musca_b1_scc_error_t
musca_b1_scc_set_pinmode(struct musca_b1_scc_dev_t* dev, uint64_t pin_mask,
enum pinmode_select_t mode);
/**
* \brief Sets default input values for the selected pins
*
* \param[in] dev SCC device pointer \ref musca_b1_scc_dev_t
* \param[in] altfunc The selected alternate function that is set the
* specified default in value \ref gpio_altfunc_t
* \param[in] pin_num Pin number
* \param[in] default_in_value True if the in value needs to be set to 1,
* false if it needs to be 0
*
* \return Returns error code. \ref musca_b1_scc_error_t
*
* \note This function doesn't check if scc_base is NULL.
* \note If no alternate function is selected, the function won't do anything
*/
enum musca_b1_scc_error_t
musca_b1_scc_set_default_in(struct musca_b1_scc_dev_t* dev,
enum gpio_altfunc_t altfunc,
uint32_t pin_num,
bool default_in_value);
#ifdef __cplusplus
}
#endif
#endif /* __MUSCA_B1_SCC_DRV_H__ */

View File

@ -0,0 +1,225 @@
/*
* 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.
*/
/**
* \file timer_cmsdk_drv.c
* \brief Generic driver for CMSDK APB Timers.
* The timer is a 32-bit down-counter with the following features:
* - optional programmable external clock source
* - programmable interrupt source, triggered if counter reaches 0
* - automatic reload if counter reaches 0
*/
#include "timer_cmsdk_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))))
/**
* \brief Timer register map structure
*
*/
struct timer_cmsdk_reg_map_t {
volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */
volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */
volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */
union {
volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt
* status register
*/
volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt
* clear register
*/
}intreg;
};
/**
* \brief CTRL register bit definitions
*
*/
enum ctrl_reg_bits_t {
CTRL_REG_ENUM_ENABLE_INDEX = 0,
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
};
/**
* \brief INTSTATUS/INTCLEAR register bit definitions
*
*/
enum interrupt_reg_bits_t {
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
};
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
if (dev->data->is_initialized == 0) {
register_map->ctrl = 0;
register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
dev->data->is_initialized = 1;
}
}
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
{
return dev->data->is_initialized;
}
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl,
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
}
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl,
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
}
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
}
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
}
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return GET_BIT(register_map->intreg.intstatus,
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
}
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
SET_BIT(register_map->intreg.intclear,
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
}
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->value;
}
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
uint32_t reload)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->reload = reload;
}
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
register_map->value = register_map->reload;
}
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->reload;
}
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
{
struct timer_cmsdk_reg_map_t* register_map =
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
return register_map->reload - register_map->value;
}

View File

@ -0,0 +1,254 @@
/*
* 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.
*/
/**
* \file timer_cmsdk_drv.h
* \brief Generic driver for CMSDK APB Timers.
* The timer is a 32-bit down-counter with the following features:
* - optional programmable external clock source
* - programmable interrupt source, triggered if counter reaches 0
* - automatic reload if counter reaches 0
*/
#ifndef __TIMER_CMSDK_DRV_H__
#define __TIMER_CMSDK_DRV_H__
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Maximum reload value */
#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */
#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD
/** CMSDK timer device configuration structure */
struct timer_cmsdk_dev_cfg_t {
const uintptr_t base; /*!< Timer base address */
};
/** CMSDK timer device data structure */
struct timer_cmsdk_dev_data_t {
bool is_initialized; /*!< Indicates if the timer is initialized */
};
/* CMSDK timer device structure */
struct timer_cmsdk_dev_t {
const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */
struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */
};
/**
* \brief Initializes timer to a known default state, which is:
* - timer disabled
* - timer interrupt disabled
* - clock source set to internal
* - external input disabled
* - reload value maxed out
* Init should be called prior to any other process and
* it's the caller's responsibility to follow proper call order.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer is initialized.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if initialized, false otherwise
*/
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables external input, which could be used as clock source
* by calling \ref timer_cmsdk_set_clock_to_external.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables external input.
* Make sure if the timer is explicitly wanted to be stopped or set
* the clock source to internal by \ref timer_cmsdk_set_clock_to_internal
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if external input is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock source to internal.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the clock source to external.
* Make sure external input is enabled correspondingly
* by \ref timer_cmsdk_enable_external_input.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if clock source is external input.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if external, false if internal
*/
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables timer operation.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables the given hardware timer.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Enables timer interrupt.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Disables timer interrupt.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Checks if a timer interrupt is enabled.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return true if enabled, false otherwise
*/
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Gets timer interrupt status
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* * \return true if active, false otherwise
*/
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Clears timer interrupt
* The interrupt request is held until it is cleared.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Reads timer current value.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Timer value
*/
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Sets the reload value of the selected timer.
*
* New reload value takes effect when:
* - timer is restarted
* - on timer underflow
* - when timer_cmsdk_reset is called
*
* \note In r1p0 technical reference manual it's incorrectly stated
* writing the reload value automatically sets the current value also.
* r1p1 technical reference manual includes the fix.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
* \param[in] reload Timer reload value to set.
* This is the start value of the 32-bit down counter,
* which automatically reloaded if 0 is reached.
*/
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
uint32_t reload);
/**
* \brief Resets the timer counter to the reload value instantly
* (i.e. without waiting for underflow).
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*/
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Gets the reload value of the selected timer.
* This is the start value of the 32-bit down counter,
* which is automatically reloaded if 0 is reached by the counter.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Reload value of the selected timer.
*/
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev);
/**
* \brief Reads the number of ticks elapsed in the current cycle.
*
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
*
* \return Get elapsed number of ticks since last reload was set.
* Elapsed = (Reload value - Current value)
*/
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_CMSDK_DRV_H__ */

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2009-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.
*
* This file is derivative of CMSIS V5.01 Device\_Template_Vendor\Vendor\Device\Include\Device.h
* Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
*/
#ifndef __MUSCA_B1_BASE_ADDRESS_H__
#define __MUSCA_B1_BASE_ADDRESS_H__
#ifdef __cplusplus
extern "C" {
#endif
/* =========================================================================================================================== */
/* ================ Device Specific Peripheral Address Map ================ */
/* =========================================================================================================================== */
/** @addtogroup Device_Peripheral_peripheralAddr
* @{
*/
/* Non-Secure Peripheral and SRAM base address */
#define MUSCA_B1_QSPI_FLASH_NS_BASE (0x00000000UL) /*!< (Non-Secure QSPI FLASH ) Base Address */
#define MUSCA_B1_EFLASH0_NS_BASE (0x0A000000UL) /*!< (Non-Secure Embedded FLASH 0 ) Base Address */
#define MUSCA_B1_EFLASH1_NS_BASE (0x0A200000UL) /*!< (Non-Secure Embedded FLASH 1 ) Base Address */
#define MUSCA_B1_CODE_SRAM_NS_BASE (0x0A400000UL) /*!< (Non-Secure Code SRAM ) Base Address */
#define MUSCA_B1_OTP_NS_BASE (0x0E000000UL) /*!< (Non-Secure OTP ) Base Address */
#define MUSCA_B1_SRAM_NS_BASE (0x20000000UL) /*!< (Non-Secure Internal SRAM ) Base Address */
#define MUSCA_B1_BASE_ELEMENT_NS_BASE (0x40000000UL) /*!< (Non-Secure Base Peripherals ) Base Address */
#define MUSCA_B1_CMSDK_TIMER0_NS_BASE (0x40000000UL) /*!< (Non-Secure CMSDK Timer0 ) Base Address */
#define MUSCA_B1_CMSDK_TIMER1_NS_BASE (0x40001000UL) /*!< (Non-Secure CMSDK Timer1 ) Base Address */
#define MUSCA_B1_CMSDK_DUALTIMER_NS_BASE (0x40002000UL) /*!< (Non-Secure CMSDK Dual Timer ) Base Address */
#define MUSCA_B1_MHU0_NS_BASE (0x40003000UL) /*!< (Non-Secure MHU0 ) Base Address */
#define MUSCA_B1_MHU1_NS_BASE (0x40004000UL) /*!< (Non-Secure MHU1 ) Base Address */
#define MUSCA_B1_CPU_ELEMENT_NS_BASE (0x40010000UL) /*!< (Non-Secure CPU Peripherals ) Base Address */
#define MUSCA_B1_SYSTEM_INFO_NS_BASE (0x40020000UL) /*!< (Non-Secure System Info ) Base Address */
#define MUSCA_B1_CMSDK_S32KTIMER_NS_BASE (0x4002F000UL) /*!< (Non-Secure CMSDK S32K Timer ) Base Address */
#define MUSCA_B1_NSPCTRL_NS_BASE (0x40080000UL) /*!< (Non-Secure Privilege Ctrl Blk ) Base Address */
#define MUSCA_B1_CMSDK_WATCHDOG_NS_BASE (0x40081000UL) /*!< (Non-Secure CMSDK Watchdog ) Base Address */
#define MUSCA_B1_PWM0_NS_BASE (0x40101000UL) /*!< (Non-Secure PWM0 ) Base Address */
#define MUSCA_B1_PWM1_NS_BASE (0x40102000UL) /*!< (Non-Secure PWM1 ) Base Address */
#define MUSCA_B1_PWM2_NS_BASE (0x40103000UL) /*!< (Non-Secure PWM2 ) Base Address */
#define MUSCA_B1_I2S_NS_BASE (0x40104000UL) /*!< (Non-Secure I2S ) Base Address */
#define MUSCA_B1_UART0_NS_BASE (0x40105000UL) /*!< (Non-Secure UART0 ) Base Address */
#define MUSCA_B1_UART1_NS_BASE (0x40106000UL) /*!< (Non-Secure UART1 ) Base Address */
#define MUSCA_B1_I2C0_NS_BASE (0x40108000UL) /*!< (Non-Secure I2C0 ) Base Address */
#define MUSCA_B1_I2C1_NS_BASE (0x40109000UL) /*!< (Non-Secure I2C1 ) Base Address */
#define MUSCA_B1_SPI0_NS_BASE (0x4010A000UL) /*!< (Non-Secure SPI0 ) Base Address */
#define MUSCA_B1_TIMER_NS_BASE (0x4010C000UL) /*!< (Non-Secure Timer ) Base Address */
#define MUSCA_B1_RTC_NS_BASE (0x4010D000UL) /*!< (Non-Secure RTC ) Base Address */
#define MUSCA_B1_PVT_NS_BASE (0x4010E000UL) /*!< (Non-Secure PVT sensors ) Base Address */
#define MUSCA_B1_SDIO_NS_BASE (0x4010F000UL) /*!< (Non-Secure SDIO ) Base Address */
#define MUSCA_B1_GPIO_NS_BASE (0x41000000UL) /*!< (Non-Secure GPIO ) Base Address */
#define MUSCA_B1_CI_MHU_SND_NS_BASE (0x42600000UL) /*!< (Non-Secure CryptoIsland MHU Send ) Base Address */
#define MUSCA_B1_CI_MHU_RCV_NS_BASE (0x42700000UL) /*!< (Non-Secure CryptoIsland MHU Rcv ) Base Address */
#define MUSCA_B1_QSPI_REG_NS_BASE (0x42800000UL) /*!< (Non-Secure QSPI registers ) Base Address */
/* Secure Peripheral and SRAM base address */
#define MUSCA_B1_QSPI_FLASH_S_BASE (0x10000000UL) /*!< (Secure QSPI FLASH ) Base Address */
#define MUSCA_B1_EFLASH0_S_BASE (0x1A000000UL) /*!< (Secure Embedded FLASH 0 ) Base Address */
#define MUSCA_B1_EFLASH1_S_BASE (0x1A200000UL) /*!< (Secure Embedded FLASH 1 ) Base Address */
#define MUSCA_B1_CODE_SRAM_S_BASE (0x1A400000UL) /*!< (Secure Code SRAM ) Base Address */
#define MUSCA_B1_OTP_S_BASE (0x1E000000UL) /*!< (Secure OTP ) Base Address */
#define MUSCA_B1_SRAM_S_BASE (0x30000000UL) /*!< (Secure Internal SRAM ) Base Address */
#define MUSCA_B1_BASE_ELEMENT_S_BASE (0x50000000UL) /*!< (Secure Base Peripherals ) Base Address */
#define MUSCA_B1_CMSDK_TIMER0_S_BASE (0x50000000UL) /*!< (Secure CMSDK Timer0 ) Base Address */
#define MUSCA_B1_CMSDK_TIMER1_S_BASE (0x50001000UL) /*!< (Secure CMSDK Timer1 ) Base Address */
#define MUSCA_B1_CMSDK_DUALTIMER_S_BASE (0x50002000UL) /*!< (Secure CMSDK Dual Timer ) Base Address */
#define MUSCA_B1_MHU0_S_BASE (0x50003000UL) /*!< (Secure MHU0 ) Base Address */
#define MUSCA_B1_MHU1_S_BASE (0x50004000UL) /*!< (Secure MHU1 ) Base Address */
#define MUSCA_B1_CPU_ELEMENT_S_BASE (0x50010000UL) /*!< (Secure CPU Peripherals ) Base Address */
#define MUSCA_B1_SYSTEM_INFO_S_BASE (0x50020000UL) /*!< (Secure System Info ) Base Address */
#define MUSCA_B1_SYSTEM_CTRL_S_BASE (0x50021000UL) /*!< (Secure System Control ) Base Address */
#define MUSCA_B1_CMSDK_S32K_WDOG_S_BASE (0x5002E000UL) /*!< (Secure CMSDK S32K Watchdog ) Base Address */
#define MUSCA_B1_CMSDK_S32KTIMER_S_BASE (0x5002F000UL) /*!< (Secure CMSDK S32K Timer ) Base Address */
#define MUSCA_B1_SPCTRL_S_BASE (0x50080000UL) /*!< (Secure Privilege Ctrl Blk ) Base Address */
#define MUSCA_B1_CMSDK_WATCHDOG_S_BASE (0x50081000UL) /*!< (Secure CMSDK Watchdog ) Base Address */
#define MUSCA_B1_MPC_SRAM0_S_BASE (0x50083000UL) /*!< (Secure MPC SRAM Bank 0 ) Base Address */
#define MUSCA_B1_MPC_SRAM1_S_BASE (0x50084000UL) /*!< (Secure MPC SRAM Bank 1 ) Base Address */
#define MUSCA_B1_MPC_SRAM2_S_BASE (0x50085000UL) /*!< (Secure MPC SRAM Bank 2 ) Base Address */
#define MUSCA_B1_MPC_SRAM3_S_BASE (0x50086000UL) /*!< (Secure MPC SRAM Bank 3 ) Base Address */
#define MUSCA_B1_PWM0_S_BASE (0x50101000UL) /*!< (Secure PWM0 ) Base Address */
#define MUSCA_B1_PWM1_S_BASE (0x50102000UL) /*!< (Secure PWM1 ) Base Address */
#define MUSCA_B1_PWM2_S_BASE (0x50103000UL) /*!< (Secure PWM2 ) Base Address */
#define MUSCA_B1_I2S_S_BASE (0x50104000UL) /*!< (Secure I2S ) Base Address */
#define MUSCA_B1_UART0_S_BASE (0x50105000UL) /*!< (Secure UART0 ) Base Address */
#define MUSCA_B1_UART1_S_BASE (0x50106000UL) /*!< (Secure UART1 ) Base Address */
#define MUSCA_B1_I2C0_S_BASE (0x50108000UL) /*!< (Secure I2C0 ) Base Address */
#define MUSCA_B1_I2C1_S_BASE (0x50109000UL) /*!< (Secure I2C1 ) Base Address */
#define MUSCA_B1_SPI0_S_BASE (0x5010A000UL) /*!< (Secure SPI0 ) Base Address */
#define MUSCA_B1_SCC_S_BASE (0x5010B000UL) /*!< (Secure SCC ) Base Address */
#define MUSCA_B1_TIMER_S_BASE (0x5010C000UL) /*!< (Secure Timer ) Base Address */
#define MUSCA_B1_RTC_S_BASE (0x5010D000UL) /*!< (Secure RTC ) Base Address */
#define MUSCA_B1_PVT_S_BASE (0x5010E000UL) /*!< (Secure PVT sensors ) Base Address */
#define MUSCA_B1_SDIO_S_BASE (0x5010F000UL) /*!< (Secure SDIO ) Base Address */
#define MUSCA_B1_GPIO_S_BASE (0x51000000UL) /*!< (Secure GPIO ) Base Address */
#define MUSCA_B1_QSPI_MPC_S_BASE (0x52000000UL) /*!< (Secure QSPI MPC ) Base Address */
#define MUSCA_B1_CODE_SRAM_MPC_S_BASE (0x52100000UL) /*!< (Secure Code SRAM MPC ) Base Address */
#define MUSCA_B1_EFLASH0_MPC_S_BASE (0x52200000UL) /*!< (Secure Embedded Flash 0 MPC ) Base Address */
#define MUSCA_B1_EFLASH1_MPC_S_BASE (0x52300000UL) /*!< (Secure Embedded Flash 1 MPC ) Base Address */
#define MUSCA_B1_EFLASH0_REG_MAP_S_BASE (0x52400000UL) /*!< (Secure GFC100 EFlash0 controller ) Base Address */
#define MUSCA_B1_EFLASH1_REG_MAP_S_BASE (0x52500000UL) /*!< (Secure GFC100 EFlash1 controller ) Base Address */
#define MUSCA_B1_CI_MHU_SND_S_BASE (0x52600000UL) /*!< (Secure CryptoIsland MHU Sender ) Base Address */
#define MUSCA_B1_CI_MHU_RCV_S_BASE (0x52700000UL) /*!< (Secure CryptoIsland MHU Receiver ) Base Address */
#define MUSCA_B1_QSPI_REG_S_BASE (0x52800000UL) /*!< (Secure QSPI registers ) Base Address */
#define MUSCA_B1_CRYPTO_MPC_S_BASE (0x52E00000UL) /*!< (Secure CryptoIsland MPC ) Base Address */
/* MPC memory range bases and limits */
/* Internal SRAM */
#define MPC_ISRAM0_RANGE_BASE_NS (0x20000000UL)
#define MPC_ISRAM0_RANGE_LIMIT_NS (0x2001FFFFUL)
#define MPC_ISRAM0_RANGE_BASE_S (0x30000000UL)
#define MPC_ISRAM0_RANGE_LIMIT_S (0x3001FFFFUL)
#define MPC_ISRAM1_RANGE_BASE_NS (0x20020000UL)
#define MPC_ISRAM1_RANGE_LIMIT_NS (0x2003FFFFUL)
#define MPC_ISRAM1_RANGE_BASE_S (0x30020000UL)
#define MPC_ISRAM1_RANGE_LIMIT_S (0x3003FFFFUL)
#define MPC_ISRAM2_RANGE_BASE_NS (0x20040000UL)
#define MPC_ISRAM2_RANGE_LIMIT_NS (0x2005FFFFUL)
#define MPC_ISRAM2_RANGE_BASE_S (0x30040000UL)
#define MPC_ISRAM2_RANGE_LIMIT_S (0x3005FFFFUL)
#define MPC_ISRAM3_RANGE_BASE_NS (0x20060000UL)
#define MPC_ISRAM3_RANGE_LIMIT_NS (0x2007FFFFUL)
#define MPC_ISRAM3_RANGE_BASE_S (0x30060000UL)
#define MPC_ISRAM3_RANGE_LIMIT_S (0x3007FFFFUL)
/* Code SRAM */
#define MPC_CODE_SRAM_RANGE_BASE_NS (0x0A400000UL)
#define MPC_CODE_SRAM_RANGE_LIMIT_NS (0x0A47FFFFUL)
#define MPC_CODE_SRAM_RANGE_BASE_S (0x1A400000UL)
#define MPC_CODE_SRAM_RANGE_LIMIT_S (0x1A47FFFFUL)
/* QSPI Flash */
#define MPC_QSPI_RANGE_BASE_NS (0x00000000UL)
#define MPC_QSPI_RANGE_LIMIT_NS (0x007FFFFFUL)
#define MPC_QSPI_RANGE_BASE_S (0x10000000UL)
#define MPC_QSPI_RANGE_LIMIT_S (0x107FFFFFUL)
/* EFlash */
#define MPC_EFLASH0_RANGE_BASE_NS (0x0A000000UL)
#define MPC_EFLASH0_RANGE_LIMIT_NS (0x0A1FFFFFUL)
#define MPC_EFLASH0_RANGE_BASE_S (0x1A000000UL)
#define MPC_EFLASH0_RANGE_LIMIT_S (0x1A1FFFFFUL)
#define MPC_EFLASH1_RANGE_BASE_NS (0x0A200000UL)
#define MPC_EFLASH1_RANGE_LIMIT_NS (0x0A3FFFFFUL)
#define MPC_EFLASH1_RANGE_BASE_S (0x1A200000UL)
#define MPC_EFLASH1_RANGE_LIMIT_S (0x1A3FFFFFUL)
/** @} */ /* End of group Device_Peripheral_peripheralAddr */
#ifdef __cplusplus
}
#endif
#endif /* __MUSCA_B1_BASE_ADDRESS_H__ */

View File

@ -0,0 +1,25 @@
/*
* 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.
*/
#ifndef __PLATFORM_DESCRIPTION_H__
#define __PLATFORM_DESCRIPTION_H__
#include "platform_base_address.h"
#include "platform_pins.h"
#include "platform_regs.h"
#include "cmsis.h"
#endif /* __PLATFORM_DESCRIPTION_H__ */

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 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.
*/
#ifndef __PLATFORM_IRQ_H__
#define __PLATFORM_IRQ_H__
/* ========================================================================== */
/* ============= Interrupt Number Definition ================ */
/* ========================================================================== */
typedef enum IRQn
{
/* ==================== Core Specific Interrupt Numbers =================== */
NonMaskableInt_IRQn = -14, /* -14 Non Maskable Interrupt */
HardFault_IRQn = -13, /* -13 HardFault Interrupt */
MemoryManagement_IRQn = -12, /* -12 Memory Management Interrupt */
BusFault_IRQn = -11, /* -11 Bus Fault Interrupt */
UsageFault_IRQn = -10, /* -10 Usage Fault Interrupt */
SecureFault_IRQn = -9, /* -9 Secure Fault Interrupt */
SVCall_IRQn = -5, /* -5 SV Call Interrupt */
DebugMonitor_IRQn = -4, /* -4 Debug Monitor Interrupt */
PendSV_IRQn = -2, /* -2 Pend SV Interrupt */
SysTick_IRQn = -1, /* -1 System Tick Interrupt */
/* ==================== SSE-200 Interrupt Numbers ========================= */
NS_WATCHDOG_RESET_IRQn = 0, /* NonSecure Wdog Rst Request Interrupt */
NS_WATCHDOG_IRQn = 1, /* Non-Secure Watchdog Interrupt */
S32K_TIMER_IRQn = 2, /* S32K Timer Interrupt */
TIMER0_IRQn = 3, /* CMSDK Timer 0 Interrupt */
TIMER1_IRQn = 4, /* CMSDK Timer 1 Interrupt */
DUALTIMER_IRQn = 5, /* CMSDK Dual Timer Interrupt */
MHU0_IRQn = 6, /* Message Handling Unit 0 Interrupt */
MHU1_IRQn = 7, /* Message Handling Unit 1 Interrupt */
/* Reserved = 8, Reserved */
S_MPC_COMBINED_IRQn = 9, /* Secure Combined MPC Interrupt */
S_PPC_COMBINED_IRQn = 10, /* Secure Combined PPC Interrupt */
S_MSC_COMBINED_IRQn = 11, /* Secure Combined MSC Interrupt */
S_BRIDGE_ERR_IRQn = 12, /* Secure Bridge Error Combined Interrupt*/
I_CACHE_INV_ERR_IRQn = 13, /* ICache Invalidation Interrupt */
/* Reserved = 14, Reserved */
SYS_PPU_IRQn = 15, /* System PPU Interrupt */
CPU0_PPU_IRQn = 16, /* CPU0 PPU Interrupt */
CPU1_PPU_IRQn = 17, /* CPU1 PPU Interrupt */
CPU0_DGB_PPU_IRQn = 18, /* CPU0 Debug PPU Interrupt */
CPU1_DGB_PPU_IRQn = 19, /* CPU1 Debug PPU Interrupt */
/* Reserved = 20, Reserved */
/* Reserved = 21, Reserved */
RAM0_PPU_IRQn = 22, /* RAM 0 PPU Interrupt */
RAM1_PPU_IRQn = 23, /* RAM 1 PPU Interrupt */
RAM2_PPU_IRQn = 24, /* RAM 2 PPU Interrupt */
RAM3_PPU_IRQn = 25, /* RAM 3 PPU Interrupt */
DEBUG_PPU_IRQn = 26, /* Debug PPU Interrupt */
/* Reserved = 27, Reserved */
CPUn_CTI_IRQ0 = 28, /* CPUn CTI Interrupt 0 */
CPUn_CTI_IRQ1 = 29, /* CPUn CTI Interrupt 1 */
/* Reserved = 30, Reserved */
/* Reserved = 31, Reserved */
/* ============= Musca B1 Specific Expansion Interrupt Numbers ============= */
/* Reserved = 32, Reserved */
GpTimer_IRQn = 33, /* General Purpose Timer Interrupt */
I2C0_IRQn = 34, /* I2C0 Interrupt */
I2C1_IRQn = 35, /* I2C1 Interrupt */
I2S_IRQn = 36, /* I2S Interrupt */
SPI_IRQn = 37, /* SPI Interrupt */
QSPI_IRQn = 38, /* QSPI Interrupt */
UART0_Rx_IRQn = 39, /* UART0 receive FIFO interrupt */
UART0_Tx_IRQn = 40, /* UART0 transmit FIFO interrupt */
UART0_RxTimeout_IRQn = 41, /* UART0 receive timeout interrupt */
UART0_ModemStatus_IRQn = 42, /* UART0 modem status interrupt */
UART0_Error_IRQn = 43, /* UART0 error interrupt */
UART0_IRQn = 44, /* UART0 interrupt */
UART1_Rx_IRQn = 45, /* UART1 receive FIFO interrupt */
UART1_Tx_IRQn = 46, /* UART1 transmit FIFO interrupt */
UART1_RxTimeout_IRQn = 47, /* UART1 receive timeout interrupt */
UART1_ModemStatus_IRQn = 48, /* UART1 modem status interrupt */
UART1_Error_IRQn = 49, /* UART1 error interrupt */
UART1_IRQn = 50, /* UART1 interrupt */
GPIO_0_IRQn = 51, /* GPIO 0 interrupt */
GPIO_1_IRQn = 52, /* GPIO 1 interrupt */
GPIO_2_IRQn = 53, /* GPIO 2 interrupt */
GPIO_3_IRQn = 54, /* GPIO 3 interrupt */
GPIO_4_IRQn = 55, /* GPIO 4 interrupt */
GPIO_5_IRQn = 56, /* GPIO 5 interrupt */
GPIO_6_IRQn = 57, /* GPIO 6 interrupt */
GPIO_7_IRQn = 58, /* GPIO 7 interrupt */
GPIO_8_IRQn = 59, /* GPIO 8 interrupt */
GPIO_9_IRQn = 60, /* GPIO 9 interrupt */
GPIO_10_IRQn = 61, /* GPIO 10 interrupt */
GPIO_11_IRQn = 62, /* GPIO 11 interrupt */
GPIO_12_IRQn = 63, /* GPIO 12 interrupt */
GPIO_13_IRQn = 64, /* GPIO 13 interrupt */
GPIO_14_IRQn = 65, /* GPIO 14 interrupt */
GPIO_15_IRQn = 66, /* GPIO 15 interrupt */
GPIO_Combined_IRQn = 67, /* GPIO Combined interrupt */
PVT_IRQn = 68, /* PVT sensor interrupt */
/* Reserved = 69, Reserved */
PWM_0_IRQn = 70, /* PWM0 interrupt */
RTC_IRQn = 71, /* RTC interrupt */
GpTimer1_IRQn = 72, /* General Purpose Timer1 Interrupt */
GpTimer0_IRQn = 73, /* General Purpose Timer0 Interrupt */
PWM_1_IRQn = 74, /* PWM1 interrupt */
PWM_2_IRQn = 75, /* PWM2 interrupt */
GPIO_Combined_NS_IRQn = 76, /* GPIO Combined Non-Secure interrupt */
SDIO_IRQn = 77, /* SDIO interrupt */
/* Reserved = 83:78 Reserved */
CryptoSS_Reset_Status_IRQn = 84, /* Crypto SS reset status */
HostMHUS0_Int_Acc_NR2R_IRQn = 85, /* MHU0 Sender IRQ not-ready to ready */
HostMHUS0_Int_Acc_R2NR_IRQn = 86, /* MHU0 Sender IRQ ready to not ready */
HostMHUR0_IRQ_Reg0_IRQn = 87, /* MHU0 Receiver IRQ Register 0 */
HostMHUR0_IRQ_Reg1_IRQn = 88, /* MHU0 Receiver IRQ Register 1 */
HostMHUR0_IRQComb_IRQn = 89, /* MHU0 Receiver IRQ combined */
HostMHUS1_Int_Acc_NR2R_IRQn = 90, /* MHU1 Sender IRQ not-ready to ready */
HostMHUS1_Int_Acc_R2NR_IRQn = 91, /* MHU1 Sender IRQ ready to not ready */
HostMHUR1_IRQ_Reg0_IRQn = 92, /* MHU1 Receiver IRQ Register 0 */
HostMHUR1_IRQ_Reg1_IRQn = 93, /* MHU1 Receiver IRQ Register 1 */
HostMHUR1_IRQComb_IRQn = 94, /* MHU1 Receiver IRQ combined */
EFlash0_Controller_IRQn = 95, /* GFC-100 EFlash 0 controller interrupt */
EFlash1_Controller_IRQn = 96, /* GFC-100 EFlash 1 controller interrupt */
/* Reserved = 127:97 Reserved */
} IRQn_Type;
#endif /* __PLATFORM_IRQ_H__ */

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2016-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.
*/
/**
* \file platform_pins.h
* \brief This file defines all the pins for this platform.
*/
#ifndef __MUSCA_B1_PINS_H__
#define __MUSCA_B1_PINS_H__
/* AHB GPIO pin names */
enum gpio_pin_name_t {
AHB_GPIO0_0 = 0U,
AHB_GPIO0_1,
AHB_GPIO0_2,
AHB_GPIO0_3,
AHB_GPIO0_4,
AHB_GPIO0_5,
AHB_GPIO0_6,
AHB_GPIO0_7,
AHB_GPIO0_8,
AHB_GPIO0_9,
AHB_GPIO0_10,
AHB_GPIO0_11,
AHB_GPIO0_12,
AHB_GPIO0_13,
AHB_GPIO0_14,
AHB_GPIO0_15,
};
#endif /* __MUSCA_B1_PINS_H__ */

View File

@ -0,0 +1,324 @@
/*
* Copyright (c) 2016-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.
*/
#ifndef __MUSCA_B1_PLATFORM_REGS_H__
#define __MUSCA_B1_PLATFORM_REGS_H__
#include <stdint.h>
#include "platform_base_address.h"
/* System info memory mapped register access structure */
struct sysinfo_t {
volatile uint32_t sysversion; /* (R/ ) System version */
volatile uint32_t sysconfig; /* (R/ ) System configuration */
volatile uint32_t reserved0[1008];
volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */
volatile uint32_t reserved1[3];
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 */
};
/* Secure System Control (SYSCTRL) alias */
#define CMSDK_SYSCTRL_BASE_S MUSCA_B1_SYSTEM_CTRL_S_BASE
/* System control memory mapped register access structure */
struct sysctrl_t {
volatile uint32_t secdbgstat; /* (R/ ) Secure Debug Configuration
* Status Register*/
volatile uint32_t secdbgset; /* ( /W) Secure Debug Configuration
* Set Register */
volatile uint32_t secdbgclr; /* ( /W) Secure Debug Configuration
* Clear Register */
volatile uint32_t scsecctrl; /* (R/W) System Control Security
* Control Register */
volatile uint32_t fclk_div; /* (R/W) Fast Clock Divider
* Configuration Register */
volatile uint32_t sysclk_div; /* (R/W) System Clock Divider
* Configuration Register */
volatile uint32_t clockforce; /* (R/W) Clock Forces */
volatile uint32_t reserved1[57];
volatile uint32_t resetsyndrome; /* (R/W) Reset syndrome */
volatile uint32_t resetmask; /* (R/W) Reset MASK */
volatile uint32_t swreset; /* ( /W) Software Reset */
volatile uint32_t gretreg; /* (R/W) General Purpose Retention
* Register */
volatile uint32_t initsvtor0; /* (R/W) Initial Secure Reset Vector
* Register For CPU 0 */
volatile uint32_t initsvtor1; /* (R/W) Initial Secure Reset
* Vector Register For CPU 1*/
volatile uint32_t cpuwait; /* (R/W) CPU Boot wait control
* after reset */
volatile uint32_t nmi_enable; /* (R/W) NMI Enable Register.*/
volatile uint32_t wicctrl; /* (R/W) CPU WIC Request and
* Acknowledgement */
volatile uint32_t ewctrl; /* (R/W) External Wakeup Control */
volatile uint32_t reserved2[54];
volatile uint32_t pdcm_pd_sys_sense; /* (R/W) Power Control Dependency
* Matrix PD_SYS
* Power Domain Sensitivity.*/
volatile uint32_t reserved3[2];
volatile uint32_t pdcm_pd_sram0_sense; /* (R/W) Power Control Dependency
* Matrix PD_SRAM0 Power
* Domain Sensitivity.*/
volatile uint32_t pdcm_pd_sram1_sense; /* (R/W) Power Control Dependency
* Matrix PD_SRAM1 Power
* Domain Sensitivity.*/
volatile uint32_t pdcm_pd_sram2_sense; /* (R/W) Power Control Dependency
* Matrix PD_SRAM2 Power
* Domain Sensitivity.*/
volatile uint32_t pdcm_pd_sram3_sense; /* (R/W) Power Control Dependency
* Matrix PD_SRAM3 Power
* Domain Sensitivity.*/
volatile uint32_t reserved4[877];
volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */
volatile uint32_t reserved5[3];
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 */
};
/* Secure Privilege Control */
#define CMSDK_SPCTRL ((struct spctrl_def*)MUSCA_B1_SPCTRL_S_BASE)
/* SPCTRL memory mapped register access structure */
struct spctrl_def {
volatile uint32_t spcsecctrl; /* (R/W) Secure Configuration Control
Register */
volatile uint32_t buswait; /* (R/W) Bus Access wait control after reset.*/
volatile uint32_t reserved[2];
volatile uint32_t secrespcfg; /* (R/W) Security Violation Response
* Configuration register.*/
volatile uint32_t nsccfg; /* (R/W) Non Secure Callable Configuration
* for IDAU. */
volatile uint32_t reserved2;
volatile uint32_t secmpcintstat; /* (R/W) Secure MPC Interrupt Status. */
volatile uint32_t secppcintstat; /* (R/W) Secure PPC Interrupt Status. */
volatile uint32_t secppcintclr; /* (R/W) Secure PPC Interrupt Clear. */
volatile uint32_t secppcinten; /* (R/W) Secure PPC Interrupt Enable. */
volatile uint32_t reserved3;
volatile uint32_t secmscintstat; /* (R/W) Secure MSC Interrupt Status. */
volatile uint32_t secmscintclr; /* (R/W) Secure MSC Interrupt Clear. */
volatile uint32_t secmscinten; /* (R/W) Secure MSC Interrupt Enable. */
volatile uint32_t reserved4;
volatile uint32_t brgintstat; /* (R/W) Bridge Buffer Error Interrupt Status. */
volatile uint32_t brgintclr; /* (R/W) Bridge Buffer Error Interrupt Clear. */
volatile uint32_t brginten; /* (R/W) Bridge Buffer Error Interrupt Enable. */
volatile uint32_t reserved5;
volatile uint32_t ahbnsppc0; /* (R/W) Non-Secure Access AHB slave Peripheral
* Protection Control #0 */
volatile uint32_t reserved6[3];
volatile uint32_t ahbnsppcexp0; /* (R/W) Expansion 0 Non_Secure Access AHB slave
* Peripheral Protection Control */
volatile uint32_t ahbnsppcexp1; /* (R/W) Expansion 1 Non_Secure Access AHB slave
* Peripheral Protection Control */
volatile uint32_t ahbnsppcexp2; /* (R/W) Expansion 2 Non_Secure Access AHB slave
* Peripheral Protection Control */
volatile uint32_t ahbnsppcexp3; /* (R/W) Expansion 3 Non_Secure Access AHB slave
* Peripheral Protection Control */
volatile uint32_t apbnsppc0; /* (R/W) Non-Secure Access APB slave Peripheral
* Protection Control #0 */
volatile uint32_t apbnsppc1; /* (R/W) Non-Secure Access APB slave Peripheral
* Protection Control #1 */
volatile uint32_t reserved7[2];
volatile uint32_t apbnsppcexp0; /* (R/W) Expansion 0 Non_Secure Access APB slave
* Peripheral Protection Control */
volatile uint32_t apbnsppcexp1; /* (R/W) Expansion 1 Non_Secure Access APB slave
* Peripheral Protection Control */
volatile uint32_t apbnsppcexp2; /* (R/W) Expansion 2 Non_Secure Access APB slave
* Peripheral Protection Control */
volatile uint32_t apbnsppcexp3; /* (R/W) Expansion 3 Non_Secure Access APB slave
* Peripheral Protection Control */
volatile uint32_t ahbspppc0; /* (R/W) Secure Unprivileged Access AHB slave
* Peripheral Protection Control #0. */
volatile uint32_t reserved8[3];
volatile uint32_t ahbspppcexp0; /* (R/W) Expansion 0 Secure Unprivileged Access
* AHB slave Peripheral Protection Control. */
volatile uint32_t ahbspppcexp1; /* (R/W) Expansion 1 Secure Unprivileged Access
* AHB slave Peripheral Protection Control. */
volatile uint32_t ahbspppcexp2; /* (R/W) Expansion 2 Secure Unprivileged Access
* AHB slave Peripheral Protection Control. */
volatile uint32_t ahbspppcexp3; /* (R/W) Expansion 3 Secure Unprivileged Access
* AHB slave Peripheral Protection Control. */
volatile uint32_t apbspppc0; /* (R/W) Secure Unprivileged Access APB slave
* Peripheral Protection Control #0 */
volatile uint32_t apbspppc1; /* (R/W) Secure Unprivileged Access APB slave
* Peripheral Protection Control #1 */
volatile uint32_t reserved9[2];
volatile uint32_t apbspppcexp0; /* (R/W) Expansion 0 Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbspppcexp1; /* (R/W) Expansion 1 Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbspppcexp2; /* (R/W) Expansion 2 Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbspppcexp3; /* (R/W) Expansion 3 Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t nsmscexp; /* (R/W) Expansion MSC Non-Secure Configuration */
volatile uint32_t reserved10[959];
volatile uint32_t pidr4; /* (R/ ) Peripheral ID 4 */
volatile uint32_t reserved11[3];
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 */
};
/* PPC interrupt position mask */
#define CMSDK_APB_PPC0_INT_POS_MASK (1UL << 0)
#define CMSDK_APB_PPC1_INT_POS_MASK (1UL << 1)
#define CMSDK_APB_PPCEXP0_INT_POS_MASK (1UL << 4)
#define CMSDK_APB_PPCEXP1_INT_POS_MASK (1UL << 5)
#define CMSDK_APB_PPCEXP2_INT_POS_MASK (1UL << 6)
#define CMSDK_APB_PPCEXP3_INT_POS_MASK (1UL << 7)
#define CMSDK_AHB_PPCEXP0_INT_POS_MASK (1UL << 20)
#define CMSDK_AHB_PPCEXP1_INT_POS_MASK (1UL << 21)
#define CMSDK_AHB_PPCEXP2_INT_POS_MASK (1UL << 22)
#define CMSDK_AHB_PPCEXP3_INT_POS_MASK (1UL << 23)
/* Non-Secure Privilege Control */
#define CMSDK_NSPCTRL ((struct nspctrl_def*)MUSCA_B1_NSPCTRL_NS_BASE)
/* NSPCTRL memory mapped register access structure */
struct nspctrl_def {
volatile uint32_t reserved[36];
volatile uint32_t ahbnspppc0; /* (R/W) Non-Secure Unprivileged Access AHB slave
* Peripheral Protection Control #0 */
volatile uint32_t reserved3[3];
volatile uint32_t ahbnspppcexp0; /* (R/W) Expansion 0 Non-Secure Unprivileged Access
* AHB slave Peripheral Protection Control */
volatile uint32_t ahbnspppcexp1; /* (R/W) Expansion 1 Non-Secure Unprivileged Access
* AHB slave Peripheral Protection Control */
volatile uint32_t ahbnspppcexp2; /* (R/W) Expansion 2 Non-Secure Unprivileged Access
* AHB slave Peripheral Protection Control */
volatile uint32_t ahbnspppcexp3; /* (R/W) Expansion 3 Non-Secure Unprivileged Access
* AHB slave Peripheral Protection Control */
volatile uint32_t apbnspppc0; /* (R/W) Non-Secure Unprivileged Access APB slave
* Peripheral Protection Control #0 */
volatile uint32_t apbnspppc1; /* (R/W) Non-Secure Unprivileged Access APB slave
* Peripheral Protection Control #1 */
volatile uint32_t reserved4[2];
volatile uint32_t apbnspppcexp0; /* (R/W) Expansion 0 Non-Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbnspppcexp1; /* (R/W) Expansion 1 Non-Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbnspppcexp2; /* (R/W) Expansion 2 Non-Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t apbnspppcexp3; /* (R/W) Expansion 3 Non-Secure Unprivileged Access
* APB slave Peripheral Protection Control */
volatile uint32_t reserved5[960];
volatile uint32_t pidr4; /* (R/W) Peripheral ID 3 */
volatile uint32_t reserved7[3];
volatile uint32_t pidr0; /* (R/W) Peripheral ID 0 */
volatile uint32_t pidr1; /* (R/W) Peripheral ID 1 */
volatile uint32_t pidr2; /* (R/W) Peripheral ID 2 */
volatile uint32_t pidr3; /* (R/W) Peripheral ID 3 */
volatile uint32_t cidr0; /* (R/W) Component ID 0 */
volatile uint32_t cidr1; /* (R/W) Component ID 1 */
volatile uint32_t cidr2; /* (R/W) Component ID 2 */
volatile uint32_t cidr3; /* (R/W) Component ID 3 */
};
/* SSE-200 specific PPC bit definitions */
/* ARM APB PPC0 peripherals definition */
#define CMSDK_TIMER0_APB_PPC_POS 0U
#define CMSDK_TIMER1_APB_PPC_POS 1U
#define CMSDK_DTIMER_APB_PPC_POS 2U
#define CMSDK_MHU0_APB_PPC_POS 3U
#define CMSDK_MHU1_APB_PPC_POS 4U
/* The bits 31:5 are reserved */
/* End ARM APB PPC0 peripherals definition */
/* ARM APB PPC1 peripherals definition */
#define CMSDK_S32K_TIMER_PPC_POS 0U
/* The bits 31:1 are reserved */
/* End ARM APB PPC1 peripherals definition */
/* ARM AHB PPC0 peripherals definition */
/* The bits 31:0 are reserved */
/* End of ARM AHB PPC0 peripherals definition */
/* Musca B1 specific PPC bit definitions */
/* ARM AHB PPCEXP0 peripherals definition */
/* Bit 0 is reserved */
#define MUSCA_B1_GPIO_AHB_PPC_POS 1U
/* The bits 31:2 are reserved */
/* End of ARM AHB PPCEXP0 peripherals definition */
/* ARM AHB PPCEXP1 peripherals definition */
/* The bits 31:0 are reserved */
/* End of ARM AHB PPCEXP1 peripherals definition */
/* ARM AHB PPCEXP2 peripherals definition */
/* The bits 31:0 are reserved */
/* End of ARM AHB PPCEXP2 peripherals definition */
/* ARM AHB PPCEXP3 peripherals definition */
/* The bits 31:0 are reserved */
/* End of ARM AHB PPCEXP3 peripherals definition */
/* ARM APB PPCEXP0 peripherals definition */
#define MUSCA_B1_EFLASH0_CTRL_APB_PPC_POS 0U
#define MUSCA_B1_EFLASH1_CTRL_APB_PPC_POS 1U
#define MUSCA_B1_QSPI_APB_PPC_POS 2U
#define MUSCA_B1_EFLASH0_MPC_APB_PPC_POS 3U
#define MUSCA_B1_EFLASH1_MPC_APB_PPC_POS 4U
#define MUSCA_B1_SRAM_MPC_APB_PPC_POS 5U
#define MUSCA_B1_QSPI_MPC_APB_PPC_POS 6U
#define MUSCA_B1_CI_MHU0_S_APB_PPC_POS 7U
#define MUSCA_B1_CI_MHU0_R_APB_PPC_POS 8U
/* The bits 13:9 are reserved. */
#define MUSCA_B1_CI_MPC_APB_PPC_POS 14U
/* The bits 31:15 are reserved */
/* End of ARM APB PPCEXP0 peripherals definition */
/* ARM APB PPCEXP1 peripherals definition */
/* Bit 0 is reserved. */
#define MUSCA_B1_PWM0_APB_PPC_POS 1U
#define MUSCA_B1_PWM1_APB_PPC_POS 2U
#define MUSCA_B1_PWM2_APB_PPC_POS 3U
#define MUSCA_B1_I2S_APB_PPC_POS 4U
#define MUSCA_B1_UART0_APB_PPC_POS 5U
#define MUSCA_B1_UART1_APB_PPC_POS 6U
/* Bit 7 is reserved. */
#define MUSCA_B1_I2C0_APB_PPC_POS 8U
#define MUSCA_B1_I2C1_APB_PPC_POS 9U
#define MUSCA_B1_SPI_APB_PPC_POS 10U
#define MUSCA_B1_SCC_APB_PPC_POS 11U
#define MUSCA_B1_GPTIMER_APB_PPC_POS 12U
#define MUSCA_B1_RTC_APB_PPC_POS 13U
#define MUSCA_B1_PVT_APB_PPC_POS 14U
#define MUSCA_B1_SDIO_APB_PPC_POS 15U
/* The bits 31:16 are reserved */
/* End of ARM APB PPCEXP1 peripherals definition */
#endif /* __MUSCA_B1_PLATFORM_REGS_H__ */

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2009-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 file is derivative of CMSIS V5.01 \Device\ARM\ARMCM33\Source\system_ARMCM33.c
* Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
*/
#include <stdint.h>
#include "system_core_init.h"
#include "platform_description.h"
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
#define XTAL (40960000UL)
#define SYSTEM_CLOCK (XTAL)
#define SYSTEM_REFCLK (32768UL)
/*----------------------------------------------------------------------------
Externals
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
System Core Clock Variable
*----------------------------------------------------------------------------*/
uint32_t SystemCoreClock = SYSTEM_CLOCK;
uint32_t PeripheralClock = SYSTEM_CLOCK;
uint32_t RefClock = SYSTEM_REFCLK;
/*----------------------------------------------------------------------------
System Core Clock update function
*----------------------------------------------------------------------------*/
void SystemCoreClockUpdate (void)
{
SystemCoreClock = SYSTEM_CLOCK;
PeripheralClock = SYSTEM_CLOCK;
RefClock = SYSTEM_REFCLK;
}
/*----------------------------------------------------------------------------
System initialization function
*----------------------------------------------------------------------------*/
void SystemInit (void)
{
#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
extern uint32_t __Vectors;
SCB->VTOR = (uint32_t) &__Vectors;
#endif
#if defined (__FPU_USED) && (__FPU_USED == 1U)
SCB->CPACR |= ((3U << 10U*2U) | /* set CP10 Full Access */
(3U << 11U*2U) ); /* set CP11 Full Access */
#endif
#ifdef UNALIGNED_SUPPORT_DISABLE
SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
#endif
SystemCoreClock = SYSTEM_CLOCK;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2009-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 file is derivative of CMSIS V5.01 \Device\ARM\ARMCM33\Include\system_ARMCM33.h
* Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
*
*/
#ifndef __MUSCA_B1_SYSTEM_INIT_H__
#define __MUSCA_B1_SYSTEM_INIT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
extern uint32_t PeripheralClock; /*!< Peripheral Clock Frequency */
extern uint32_t RefClock; /*!< External Reference Clock Frequency */
/**
\brief Setup the microcontroller system.
Initialize the System and update the SystemCoreClock variable.
It should be called from Reset Handler within the first few steps.
The minimal feature set should be initialised for successful exit
from Reset Handler to main entry point.
*/
extern void SystemInit (void);
/**
\brief Update SystemCoreClock variable.
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
*/
extern void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* __MUSCA_B1_SYSTEM_INIT_H__ */

View File

@ -0,0 +1,51 @@
/* mbed Microcontroller Library
* Copyright (c) 2019-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 MBED_GPIO_OBJECT_H
#define MBED_GPIO_OBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
#define GPIO_PIN_NUMBER(pin) ((pin) & 0xF)
#define PINS_NUMBER (16)
/**
* \brief Object to store GPIO specific data through the configuration
*/
typedef struct gpio_s {
struct gpio_cmsdk_dev_t *gpio_dev;
uint32_t pin_num;
PinDirection direction;
} gpio_t;
struct gpio_irq_s {
/** GPIO is not available in Musca-B1 in non-secure domain, so this dummy
* structure is needed for successful build.
*/
uint32_t dummy;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,61 @@
/* mbed Microcontroller Library
* Copyright (c) 2019-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 MBED_OBJECTS_H
#define MBED_OBJECTS_H
#include "cmsis.h"
#include "PeripheralNames.h"
#include "PinNames.h"
#include "platform_description.h"
#include "device_definition.h"
#include "gpio_object.h"
#ifdef __cplusplus
extern "C" {
#endif
#if TARGET_MUSCA_B1_NS
struct serial_s {
struct uart_pl011_dev_t *uart_dev;
UARTName uart_index; /* UART device number */
IRQn_Type tx_irq;
IRQn_Type rx_irq;
IRQn_Type rx_timeout_irq;
};
#endif // TARGET_MUSCA_B1_NS
#if DEVICE_FLASH
struct flash_s {
uint8_t dummy;
};
#endif // DEVICE_FLASH
#if DEVICE_TRNG
struct trng_s {
/* nothing to be stored for now */
void *dummy;
};
#endif // DEVICE_TRNG
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,135 @@
/*
* 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.
*/
#ifndef __FLASH_LAYOUT_H__
#define __FLASH_LAYOUT_H__
/* Flash layout on Musca-B1 with BL2(single image boot, boot from eFlash 0):
*
* 0x0A00_0000 BL2 - MCUBoot (128 KB)
* 0x0A02_0000 Primary image area (832 KB):
* 0x0A02_0000 Secure image primary (320 KB)
* 0x0A07_0000 Non-secure image primary (512 KB)
* 0x0A0F_0000 Secondary image area (832 KB):
* 0x0A0F_0000 Secure image secondary (320 KB)
* 0x0A14_0000 Non-secure image secondary (512 KB)
* 0x0A1C_0000 Secure Storage Area (0.02 MB)
* 0x0A1C_5000 Internal Trusted Storage Area (0.02 MB)
* 0x0A1C_A000 NV counters area (4 KB)
* 0x0A1C_B000 Unused
*/
/* This header file is included from linker scatter file as well, where only a
* limited C constructs are allowed. Therefore it is not possible to include
* here the platform_base_address.h to access flash related defines. To resolve
* this some of the values are redefined here with different names, these are
* marked with comment.
*/
/* Size of a Secure and of a Non-secure image */
#define FLASH_S_PARTITION_SIZE (0x50000) /* S partition: 320 KB */
#define FLASH_NS_PARTITION_SIZE (0x80000) /* NS partition: 512 KB */
/* Sector size of the flash hardware */
#define FLASH_AREA_IMAGE_SECTOR_SIZE (0x1000) /* 4 KB */
#define FLASH_TOTAL_SIZE (0x200000) /* 2 MB */
/* Flash layout info for BL2 bootloader */
/* Same as MUSCA_B1_EFLASH0_S_BASE */
#define FLASH_BASE_ADDRESS (0x1A000000)
/* Offset and size definitions of the flash partitions that are handled by the
* bootloader. The image swapping is done between IMAGE_0 and IMAGE_1, SCRATCH
* is used as a temporary storage during image swapping.
*/
#define FLASH_AREA_BL2_OFFSET (0x0)
#define FLASH_AREA_BL2_SIZE (0x20000) /* 128 KB */
#define FLASH_AREA_IMAGE_0_OFFSET (FLASH_AREA_BL2_OFFSET + \
FLASH_AREA_BL2_SIZE)
#define FLASH_AREA_IMAGE_0_SIZE (FLASH_S_PARTITION_SIZE + \
FLASH_NS_PARTITION_SIZE)
#define FLASH_AREA_IMAGE_1_OFFSET (FLASH_AREA_IMAGE_0_OFFSET + \
FLASH_AREA_IMAGE_0_SIZE)
#define FLASH_AREA_IMAGE_1_SIZE (FLASH_S_PARTITION_SIZE + \
FLASH_NS_PARTITION_SIZE)
/* Not used, only the Non-swapping firmware upgrade operation
* is supported on Musca-B1
*/
#define FLASH_AREA_IMAGE_SCRATCH_OFFSET (FLASH_AREA_IMAGE_1_OFFSET + \
FLASH_AREA_IMAGE_1_SIZE)
#define FLASH_AREA_IMAGE_SCRATCH_SIZE (0)
/* Not used, only the Non-swapping firmware upgrade operation
* is supported on Musca-B1. The maximum number of status entries
* supported by the bootloader.
*/
#define BOOT_STATUS_MAX_ENTRIES (0)
/* Maximum number of image sectors supported by the bootloader. */
#define BOOT_MAX_IMG_SECTORS ((FLASH_S_PARTITION_SIZE + \
FLASH_NS_PARTITION_SIZE) / \
FLASH_AREA_IMAGE_SECTOR_SIZE)
/* NV Counters definitions */
#define FLASH_NV_COUNTERS_AREA_OFFSET (FLASH_AREA_IMAGE_SCRATCH_OFFSET + \
FLASH_AREA_IMAGE_SCRATCH_SIZE)
#define FLASH_NV_COUNTERS_AREA_SIZE (0x14) /* 20 Bytes */
/* Offset and size definition in flash area used by assemble.py */
#define SECURE_IMAGE_OFFSET 0x0
/* Value comes from FLASH_S_PARTITION_SIZE */
#define SECURE_IMAGE_MAX_SIZE 0x50000
#define NON_SECURE_IMAGE_OFFSET 0x50000
/* Comes from FLASH_NS_PARTITION_SIZE */
#define NON_SECURE_IMAGE_MAX_SIZE 0x80000
/* Concatenated binary size used by imgtool.py */
#define SIGN_BIN_SIZE (FLASH_S_PARTITION_SIZE + \
FLASH_NS_PARTITION_SIZE)
/* NV Counters definitions */
#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
#define TFM_NV_COUNTERS_AREA_SIZE FLASH_NV_COUNTERS_AREA_SIZE
#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
/* Use eFlash 0 memory to store Code data */
#define S_ROM_ALIAS_BASE (0x1A000000)
#define NS_ROM_ALIAS_BASE (0x0A000000)
#define TOTAL_ROM_SIZE FLASH_TOTAL_SIZE
/* Internal SRAM memory is used to store RW data */
#define S_RAM_ALIAS_BASE (0x30000000)
#define NS_RAM_ALIAS_BASE (0x20000000)
#define TOTAL_RAM_SIZE (0x80000) /* 512 KB */
/* QSPi flash area is used by the Flash API */
#define S_QSPI_ALIAS_BASE (0x10000000)
#define NS_QSPI_ALIAS_BASE (0x00000000)
#define QSPI_FLASH_TOTAL_SIZE (0x00800000) /* 8MB */
/* Shared data area between bootloader and runtime firmware.
* Shared data area is allocated at the beginning of the RAM, it is overlapping
* with TF-M Secure code's MSP stack
*/
#define BOOT_TFM_SHARED_DATA_BASE S_RAM_ALIAS_BASE
#define BOOT_TFM_SHARED_DATA_SIZE (0x400)
#endif /* __FLASH_LAYOUT_H__ */

View File

@ -0,0 +1,125 @@
/*
* 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.
*/
#ifndef __REGION_DEFS_H__
#define __REGION_DEFS_H__
#include "flash_layout.h"
#define BL2_HEAP_SIZE 0x0001000
#define BL2_MSP_STACK_SIZE 0x0001000
#define S_HEAP_SIZE 0x0004000
#define S_MSP_STACK_SIZE_INIT 0x0000400
#define S_MSP_STACK_SIZE 0x0000800
#define S_PSP_STACK_SIZE 0x0000800
#define NS_HEAP_SIZE 0x0001000
#define NS_MSP_STACK_SIZE 0x0000400
#define NS_PSP_STACK_SIZE 0x0000C00
/*
* MPC granularity is 128 KB on Musca B1. Alignment
* of partitions is defined in accordance with this constraint.
*/
#define S_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_IMAGE_0_OFFSET)
#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_IMAGE_1_OFFSET)
#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_IMAGE_0_OFFSET \
+ FLASH_S_PARTITION_SIZE)
/*
* Boot partition structure if MCUBoot is used:
* 0x0_0000 Bootloader header
* 0x0_0400 Image area
* 0x1_FC00 Trailer
*/
/* IMAGE_CODE_SIZE is the space available for the software binary image.
* It is less than the FLASH_PARTITION_SIZE because we reserve space
* for the image header and trailer introduced by the bootloader.
*/
#define BL2_HEADER_SIZE (0x400)
#define BL2_TRAILER_SIZE (0x400)
#define IMAGE_S_CODE_SIZE \
(FLASH_S_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
#define IMAGE_NS_CODE_SIZE \
(FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
#define CMSE_VENEER_REGION_SIZE (0x380)
/* Alias definitions for secure and non-secure areas*/
#define S_ROM_ALIAS(x) (S_ROM_ALIAS_BASE + x)
#define NS_ROM_ALIAS(x) (NS_ROM_ALIAS_BASE + x)
#define S_RAM_ALIAS(x) (S_RAM_ALIAS_BASE + x)
#define NS_RAM_ALIAS(x) (NS_RAM_ALIAS_BASE + x)
/* Secure regions */
#define S_IMAGE_PRIMARY_AREA_OFFSET \
(S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE)
#define S_CODE_START (S_ROM_ALIAS(S_IMAGE_PRIMARY_AREA_OFFSET))
#define S_CODE_SIZE (IMAGE_S_CODE_SIZE - CMSE_VENEER_REGION_SIZE)
#define S_CODE_LIMIT (S_CODE_START + S_CODE_SIZE - 1)
#define S_DATA_START (S_RAM_ALIAS(0x0))
#define S_DATA_SIZE (TOTAL_RAM_SIZE / 2)
#define S_DATA_LIMIT (S_DATA_START + S_DATA_SIZE - 1)
/* CMSE Veneers region */
#define CMSE_VENEER_REGION_START (S_CODE_LIMIT + 1)
/* Non-secure regions */
#define NS_IMAGE_PRIMARY_AREA_OFFSET \
(NS_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE)
#define NS_CODE_START (NS_ROM_ALIAS(NS_IMAGE_PRIMARY_AREA_OFFSET))
#define NS_CODE_SIZE (IMAGE_NS_CODE_SIZE)
#define NS_CODE_LIMIT (NS_CODE_START + NS_CODE_SIZE - 1)
#define NS_DATA_START (NS_RAM_ALIAS(TOTAL_RAM_SIZE / 2))
#define NS_DATA_SIZE (TOTAL_RAM_SIZE / 2)
#define NS_DATA_LIMIT (NS_DATA_START + NS_DATA_SIZE - 1)
/* NS partition information is used for MPC and SAU configuration */
#define NS_PARTITION_START \
(NS_ROM_ALIAS(NS_IMAGE_PRIMARY_PARTITION_OFFSET))
#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE)
/* Secondary partition for new images in case of firmware upgrade */
#define SECONDARY_PARTITION_START \
(NS_ROM_ALIAS(S_IMAGE_SECONDARY_PARTITION_OFFSET))
#define SECONDARY_PARTITION_SIZE (FLASH_AREA_IMAGE_1_SIZE)
/* Code SRAM area */
#define TOTAL_CODE_SRAM_SIZE (0x00080000) /* 512 KB */
#define S_CODE_SRAM_ALIAS_BASE (0x1A400000)
#define NS_CODE_SRAM_ALIAS_BASE (0x0A400000)
/* Bootloader regions */
#define BL2_CODE_START (S_ROM_ALIAS(FLASH_AREA_BL2_OFFSET))
#define BL2_CODE_SIZE (FLASH_AREA_BL2_SIZE)
#define BL2_CODE_LIMIT (BL2_CODE_START + BL2_CODE_SIZE - 1)
#define BL2_DATA_START (S_RAM_ALIAS(0x0))
#define BL2_DATA_SIZE (TOTAL_RAM_SIZE)
#define BL2_DATA_LIMIT (BL2_DATA_START + BL2_DATA_SIZE - 1)
#endif /* __REGION_DEFS_H__ */

View File

@ -0,0 +1,251 @@
/*
* Copyright (c) 2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __TFM_IOCTL_API__
#define __TFM_IOCTL_API__
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include "tfm_api.h"
#include "tfm_platform_api.h"
#ifdef __cplusplus
extern "C" {
#endif
enum tfm_platform_ioctl_reqest_types_t {
TFM_PLATFORM_IOCTL_PIN_SERVICE,
TFM_PLATFORM_IOCTL_GPIO_SERVICE,
};
/*!
* \enum tfm_gpio_service_type_t
*
* \brief GPIO service types (supported types may vary based on the platform)
*/
enum tfm_gpio_service_type_t {
TFM_GPIO_SERVICE_TYPE_INIT = 0, /*!< Init */
TFM_GPIO_SERVICE_TYPE_PIN_CONFIG, /*!< Pin config */
TFM_GPIO_SERVICE_TYPE_PIN_WRITE, /*!< Pin write */
TFM_GPIO_SERVICE_TYPE_PIN_READ, /*!< Pin read */
TFM_GPIO_SERVICE_TYPE_PORT_CONFIG, /*!< Port config */
TFM_GPIO_SERVICE_TYPE_PORT_WRITE, /*!< Port write */
TFM_GPIO_SERVICE_TYPE_PORT_READ, /*!< Port read */
TFM_GPIO_SERVICE_TYPE_MAX = INT_MAX /*!< Max to force enum max size */
};
/*!
* \struct tfm_gpio_service_args_t
*
* \brief Argument list for each platform GPIO service
*/
struct tfm_gpio_service_args_t {
enum tfm_gpio_service_type_t type;
union {
struct gpio_config_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_CONFIG ||
TFM_GPIO_SERVICE_TYPE_PORT_CONFIG */
uint32_t pin_num_or_mask;
uint32_t direction;
} gpio_config;
struct gpio_write_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_WRITE ||
TFM_GPIO_SERVICE_TYPE_PORT_WRITE */
uint32_t pin_num_or_mask;
uint32_t value;
} gpio_write;
struct gpio_read_args { /*!< TFM_GPIO_SERVICE_TYPE_PIN_READ ||
TFM_GPIO_SERVICE_TYPE_PORT_READ */
uint32_t pin_num_or_mask;
} gpio_read;
} u;
};
/*!
* \struct tfm_gpio_service_out_t
*
* \brief Output list for each GPIO platform service
*/
struct tfm_gpio_service_out_t {
union {
uint32_t result; /*!< Generic result */
struct gpio_read_result { /*!< TFM_GPIO_SERVICE_TYPE_PIN_READ ||
TFM_GPIO_SERVICE_TYPE_PORT_READ */
uint32_t result;
uint32_t data;
} gpio_read_result;
} u;
};
/*!
* \enum tfm_pin_service_type_t
*
* \brief Pin service types
*/
enum tfm_pin_service_type_t {
TFM_PIN_SERVICE_TYPE_SET_ALTFUNC = 0, /*!< Set alternate function type */
TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN, /*!< Set default in function type */
TFM_PIN_SERVICE_TYPE_SET_PIN_MODE, /*!< Set pin mode function type */
TFM_PIN_SERVICE_TYPE_MAX = INT_MAX /*!< Max to force enum max size */
};
/*!
* \struct tfm_pin_service_args_t
*
* \brief Argument list for each platform pin service
*/
struct tfm_pin_service_args_t {
enum tfm_pin_service_type_t type;
union {
struct set_altfunc { /*!< TFM_PIN_SERVICE_TYPE_SET_ALTFUNC */
uint32_t alt_func;
uint64_t pin_mask;
} set_altfunc;
struct set_default_in { /*!< TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN */
uint32_t alt_func;
uint32_t pin_value;
bool default_in_value;
} set_default_in;
struct set_pin_mode { /*!< TFM_PIN_SERVICE_TYPE_SET_PIN_MODE */
uint64_t pin_mask;
uint32_t pin_mode;
} set_pin_mode;
} u;
};
/*!
* \brief Sets pin alternate function for the given pins
*
* \param[in] alt_func Alternate function to set (allowed values vary
* based on the platform)
* \param[in] pin_mask Pin mask of the selected pins
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_set_pin_alt_func(uint32_t alt_func, uint64_t pin_mask,
uint32_t *result);
/*!
* \brief Sets default in value to use when the alternate function is not
* selected for the pin
*
* \param[in] alt_func Alternate function to use (allowed values vary
* based on the platform)
* \param[in] pin_value Pin value to use
* \param[in] default_in_value Default in value to set
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_set_pin_default_in(uint32_t alt_func, uint32_t pin_value,
bool default_in_value, uint32_t *result);
/*!
* \brief Sets pin mode for the selected pins
*
* \param[in] pin_mask Pin mask of the selected pins
* \param[in] pin_mode Pin mode to set for the selected pins
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
uint32_t *result);
/*!
* \brief Initializes GPIO module
*
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t tfm_platform_gpio_init(uint32_t *result);
/*!
* \brief Configures a GPIO pin as input or output
*
* \param[in] pin_num Pin number of the selected pin
* \param[in] direction Direction of the pin: 0 for input, 1 for output
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_pin_config(uint32_t pin_num, uint32_t direction,
uint32_t *result);
/*!
* \brief Sets state of a selected GPIO pin
*
* \param[in] pin_num Pin number of the selected pin
* \param[in] value Value to set for the pin
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_pin_write(uint32_t pin_num, uint32_t value, uint32_t *result);
/*!
* \brief Reads state of a selected GPIO pin
*
* \param[in] pin_num Pin number of the selected pin
* \param[in,out] data Bit value read from the IO pin
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_pin_read(uint32_t pin_num, uint32_t *data, uint32_t *result);
/*!
* \brief Configures GPIO pins as input or output
*
* \param[in] pin_mask Pin mask of the selected pins
* \param[in] direction Direction of the pin: 0 for input, 1 for output
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_port_config(uint32_t pin_mask, uint32_t direction,
uint32_t *result);
/*!
* \brief Sets state of a selected GPIO pins
*
* \param[in] pin_mask Pin mask of the selected pins
* \param[in] value Value mask to set for the pins
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_port_write(uint32_t pin_mask, uint32_t value,
uint32_t *result);
/*!
* \brief Reads state of a selected GPIO pins
*
* \param[in] pin_mask Pin mask of the selected pins
* \param[in,out] data Bit value mask read from the IO pins
* \param[out] result Return error value
*
* \return Returns values as specified by the \ref tfm_platform_err_t
*/
enum tfm_platform_err_t
tfm_platform_gpio_port_read(uint32_t pin_mask, uint32_t *data,
uint32_t *result);
#ifdef __cplusplus
}
#endif
#endif /* __TFM_IOCTL_API__ */

View File

@ -1,5 +1,5 @@
/* mbed Microcontroller Library
* Copyright (c) 2016-2018 Arm Limited
* Copyright (c) 2016-2020 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
@ -43,7 +43,7 @@
#define INITIAL_SP (ZBT_SSRAM23_START + ZBT_SSRAM23_SIZE)
#endif
#elif defined(TARGET_MUSCA_A1)
#elif defined(TARGET_MUSCA_A1) || defined(TARGET_MUSCA_B1)
#if defined(__ARMCC_VERSION)
extern uint32_t Image$$ARM_LIB_HEAP$$ZI$$Base[];
@ -58,6 +58,6 @@
#error "no toolchain defined"
#endif
#endif /* TARGET_MUSCA_A1 */
#endif /* defined(TARGET_MUSCA_A1) || defined(TARGET_MUSCA_B1) */
#endif /* MBED_MBED_RTX_H */

View File

@ -8854,6 +8854,99 @@
"secure-ram-size": "0x11000"
}
},
"ARM_MUSCA_B1": {
"public": false,
"inherits": [
"Target"
],
"default_toolchain": "ARMC6",
"extra_labels": [
"ARM_SSG",
"MUSCA_B1"
],
"forced_reset_timeout": 20,
"release_versions": [
"5"
]
},
"ARM_MUSCA_B1_NS": {
"inherits": [
"NSPE_Target",
"ARM_MUSCA_B1"
],
"core": "Cortex-M33-NS",
"supported_toolchains": [
"ARMC6",
"GCC_ARM"
],
"device_has_add": [
"INTERRUPTIN",
"LPTICKER",
"SERIAL",
"SLEEP",
"USTICKER"
],
"macros": [
"__STARTUP_CLEAR_BSS",
"MBED_FAULT_HANDLER_DISABLED",
"CMSIS_NVIC_VIRTUAL",
"LPTICKER_DELAY_TICKS=3",
"MBED_MPU_CUSTOM"
],
"extra_labels_add": [
"MUSCA_B1_NS",
"PSA",
"TFM"
],
"post_binary_hook": {
"function": "ArmMuscaB1Code.binary_hook"
},
"secure_image_filename": "tfm.bin",
"overrides": {
"non-secure-rom-start": "0x0A070400",
"non-secure-rom-size": "0x7f800",
"non-secure-ram-start": "0x20040000",
"non-secure-ram-size": "0x40000"
}
},
"ARM_MUSCA_B1_S": {
"inherits": [
"SPE_Target",
"ARM_MUSCA_B1"
],
"core": "Cortex-M33",
"supported_toolchains": [
"ARMC6",
"GCC_ARM"
],
"device_has_add": [
"FLASH"
],
"macros": [
"__STARTUP_CLEAR_BSS_MULTIPLE",
"__STARTUP_COPY_MULTIPLE",
"MBED_MPU_CUSTOM",
"DAUTH_CHIP_DEFAULT",
"MBEDTLS_PSA_CRYPTO_SPM",
"MBEDTLS_ENTROPY_NV_SEED"
],
"components_add": [
"FLASHIAP"
],
"extra_labels_add": [
"MUSCA_B1_S",
"PSA",
"TFM"
],
"deliver_to_target": "ARM_MUSCA_B1_NS",
"delivery_dir": "TARGET_ARM_SSG/TARGET_MUSCA_B1/TARGET_MUSCA_B1_NS/prebuilt",
"overrides": {
"secure-rom-start": "0x1A020400",
"secure-rom-size": "0x4f800",
"secure-ram-start": "0x30000000",
"secure-ram-size": "0x40000"
}
},
"RZ_A1XX": {
"inherits": [
"Target"

View File

@ -0,0 +1,90 @@
#!/usr/bin/python
# 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.
import os
from os.path import abspath, basename, dirname, splitext, isdir
from os.path import join as path_join
import re
from argparse import Namespace
from tools.psa.tfm.bin_utils.assemble import Assembly
from tools.psa.tfm.bin_utils.imgtool import do_sign
from tools.psa.tfm.bin_utils.imgtool_lib import version
SCRIPT_DIR = dirname(abspath(__file__))
MBED_OS_ROOT = abspath(path_join(SCRIPT_DIR, os.pardir, os.pardir))
MUSCA_B1_BASE = path_join(MBED_OS_ROOT, 'targets', 'TARGET_ARM_SSG', 'TARGET_MUSCA_B1')
def musca_tfm_bin(t_self, non_secure_bin, secure_bin):
assert os.path.isfile(secure_bin)
assert os.path.isfile(non_secure_bin)
build_dir = dirname(non_secure_bin)
tempdir = path_join(build_dir, 'temp')
if not isdir(tempdir):
os.makedirs(tempdir)
flash_layout = path_join(MUSCA_B1_BASE, 'partition', 'flash_layout.h')
mcuboot_bin = path_join(MUSCA_B1_BASE, 'TARGET_MUSCA_B1_NS', 'prebuilt', 'mcuboot.bin')
ns_bin_name, ns_bin_ext = splitext(basename(non_secure_bin))
concatenated_bin = path_join(tempdir, 'tfm_' + ns_bin_name + ns_bin_ext)
signed_bin = path_join(tempdir, 'tfm_' + ns_bin_name + '_signed' + ns_bin_ext)
assert os.path.isfile(flash_layout)
#1. Concatenate secure TFM and non-secure mbed binaries
output = Assembly(flash_layout, concatenated_bin)
output.add_image(secure_bin, "SECURE")
output.add_image(non_secure_bin, "NON_SECURE")
#2. Run imgtool to sign the concatenated binary
sign_args = Namespace(
layout=flash_layout,
key=path_join(SCRIPT_DIR, 'musca_b1-root-rsa-3072.pem'),
public_key_format=None,
align=1,
dependencies=None,
version=version.decode_version('1.0'),
header_size=0x400,
pad=0xE0000,
security_counter=None,
rsa_pkcs1_15=False,
included_header=False,
infile=concatenated_bin,
outfile=signed_bin
)
do_sign(sign_args)
#3. Concatenate mcuboot and signed binary and overwrite mbed built binary file
mcuboot_image_size = find_bl2_size(flash_layout)
with open(mcuboot_bin, "rb") as mcuboot_fh, open(signed_bin, "rb") as signed_fh:
with open(non_secure_bin, "w+b") as out_fh:
out_fh.write(mcuboot_fh.read())
out_fh.seek(mcuboot_image_size)
out_fh.write(signed_fh.read())
def find_bl2_size(configFile):
bl2_size_re = re.compile(r"^#define\s+FLASH_AREA_BL2_SIZE\s+\({0,1}(0x[0-9a-fA-F]+)\){0,1}")
bl2_size = None
with open(configFile, 'r') as flash_layout_file:
for line in flash_layout_file:
m = bl2_size_re.match(line)
if m is not None:
bl2_size = int(m.group(1), 0)
break
return bl2_size

View File

@ -1,6 +1,6 @@
"""
mbed SDK
Copyright (c) 2011-2016 ARM Limited
Copyright (c) 2011-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.
@ -709,6 +709,20 @@ class ArmMuscaA1Code(object):
)
musca_tfm_bin(t_self, binf, secure_bin)
class ArmMuscaB1Code(object):
"""Musca-B1 Hooks"""
@staticmethod
def binary_hook(t_self, resources, elf, binf):
from tools.targets.ARM_MUSCA_B1 import musca_tfm_bin
configured_secure_image_filename = t_self.target.secure_image_filename
secure_bin = find_secure_image(
t_self.notify,
resources,
binf,
configured_secure_image_filename,
FileType.BIN
)
musca_tfm_bin(t_self, binf, secure_bin)
class LPC55S69Code(object):
"""LPC55S69 Hooks"""

View File

@ -2,7 +2,7 @@
A default RSA key pair is given to the Musca-A1 target.
Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/device/mcuboot.bin` and private key is in `root-rsa-3072.pem`.
Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_A1/TARGET_MUSCA_A1_NS/prebuilt/mcuboot.bin` and private key is in `musca_a1-root-rsa-3072.pem`.
DO NOT use them in production code, they are exclusively for testing!

View File

@ -0,0 +1,11 @@
# Musca-B1 RSA keypair
A default RSA key pair is given to the Musca-B1 target.
Public key was pre-compiled to `targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/TARGET_MUSCA_B1_NS/prebuilt/mcuboot.bin` and private key is in `musca_b1-root-rsa-3072.pem`.
DO NOT use them in production code, they are exclusively for testing!
Private key must be stored in a safe place outside of the repository.
`tools/psa/tfm/bin_utils/imgtool.py` can be used to generate new key pairs.

View File

@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG4gIBAAKCAYEAnLrCWr/MxU8gDE9vbFFPXAqrgLhrEMSbK8RSMglLOyeUah3V
TKhcoMB2lXsmBLETfngn1gy06LAtklKK+2n/QhCqVgyDyGVuug1fjvcrKZL8Qi0t
+YD1hSGH6qxAqMvQqDvi0uzwFEgOzyuKS6TNoQVbF2Yd3m5E/kajDdBpv4ytqRZo
Uet5kSDmgQMHiUBVS+vPZ/gxxxxUTlILYOiiUAfRz84SJs2Ogo1OZKn3xyGZJQfd
xdVf9GP6zCvaBlxZZ7AGNemqkkU15aAD/xwCtcdOlEturXOdzm8Js7GPYGyi+s13
D8wn5jZYs1L3j75JmLfpYP2XV83q0wvfokL3RNOH3uAQA5Ta/LzdvpOzSitY3JYS
8m8jujs3/vwYH3V9VAEOvj0YE7MouTQs1fvFM72HvTvkHdcCPRxyZXJDQzao+uZz
LaRh6AKcOlZNHNF2nIyqXxvrHEr1ubhvQUsnh972lB/d5vGpwgLCT6P8pANa2W94
/YTw5f09pU0brVtLAgMBAAECggGAG786mltbctEL0PIdPVV10cs3yq2bktfjys9S
Z/ZaQcpDjbfjY9NotrLsK5GmTO1WkKzQDKaqPom2P7HqVhFRdg5CQcKscAV5IWot
sT9T/mO90i9ydLoefWfOyr6dIeUXdzlG8mWtKUIKkSXZsYOnPesXUeCryA3InCXA
RzlPB3Dt68ICTQJ9vrJO7KcvJd7kWvEQAo2frmr3B/iheBInbji8LeiDMShyIu3G
Y67tpWzu0m3+lsAsYTV0GMJosniVulaZ3hYQQazHUk+zDzMSC7zryICrpjEbgzWU
HZI9EGi1B890nwUtdhlCpkr8zoWDb0BjawpftiGz7fRm7q2TQkYAWGzNKm3DZlIS
4LsRACvHnPZ17wUSze9tqP14Pb593WR3nOTiVjrJWm+4Z5hgV3QfoEqW5swOAYl4
6QmKZsCXAfGkozJiHnYcyaULkGBVegn1LQ5rcb8JUMribQddrHZxCVHrbgwh2zm/
v9CYfTtpWCnKHq+wF3mwjl6w7m4JAoHBALolVbgs919Dx0xjcPnW5MSxW3ctflI9
2ZE1BOH/Rtg5gfBwR/aToUM3a/ZgIJHQYhVty2TzUVtthtmLNTRKu2FSqWN8//GJ
wmj4bcNBshMgniHEfkutlBiP9exhdvCZX4bYpdTkJAyvOmUGjEM8QBFsod60u0z7
Bd0EIXs7PIURP0fNAUXCgSHMPjdICLljhwHinr31VEIU2/xehw8DBIJwkR/rCsPq
xBmlIwPWVjzCRTnYUxQuxCAYf+qvgNylKQKBwQDXi3UGI7t30rYNMdIjMn1GPkhW
o62BOJNCusoXiGnbVOkj8qBayf7kPu10ONBzHcYL7+SQYeVVXQY+DH033ji8oa0J
p1xMGIlx4JZEduQYlk0ke4hUNrcBQczTRA47DmMm2kIdWlaTHtB7aCJNx72IrwWn
lVTY9TWm6+yOPcpV5JfyCMM6GqoRycikgNS5IQug5hl2pFVLw+UTfxo6msYaAOnp
ICUjoeDUKS0Z8+FtzGhAkWTk8GXIiPbfu7RoN1MCgcAcah6Poq2QKTR/AJ76REdf
jwM7SgKCY1aWx9Ua+nDCCOVA4qLZjOeM7yTX0wyltX2Db+MgYdQFdM6k3o8ckFvS
G2AoA6i+Ih0/EM0QhTK9oLkCxo/Q1YpJxY/wqWASkhb26pNF0B2Aoi7zxPAcQ1I0
VrTO3h/JPHhEqKDDwuMWHO/f8fdDwtEba6YDokdSpVKygvlgXdaiz7RU7ckIDZne
n3hHuwVFqsyMbZzOtSUs2SrgDZmA9zKRA6xjEq9E/yECgcAnm7XecfSCGVNg61XN
J/sDTHCokx1QEKBm88ItPuEM7/aDp5M1+8Z+FN43rDUJ4l/BU8zxhzvISvbZshvU
h15vs1oD2yBHz356UaXrYNmbdwsn+BdeOku4zGmiLPBcg9FOk27wy+f60v/GnaUo
G9tFYbwtRnC4CZ9ZVCM9JDepPv9494lAhSPZbvYS3KW6e0sSvxXQynPuH0paIdIl
EMn0f1R8hW6ttJKHCiYCjeFP9u71ZoJe25oolpqfFHQbbocCgcAuBR4w3Qmnbscm
3b7fyy8n3AXa1gIfYjjPpR35qyp1K9thiLyj66YZIl0ACC/dt08lmI9/lguRoNIQ
AfjzZ8DByZa0caiSiFIMlgNZXdh7N3BUNNbIQk98Wd91gBlWDAiFEhrJKFPpRkmv
FySATPYcq0lcrjJb3IW2GDK4uo/jb4Nb7Cfog95W6T76XcSKHS5O8k1aI4kFPRsr
1wGZw64OkA8VXVaCaEBQ4brZ1YKB3mx4/tDqwn0I6bqkGRX3RJg=
-----END RSA PRIVATE KEY-----