joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers register_gateway.h Source File

register_gateway.h

00001 /*
00002  * Copyright (c) 2015-2015, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef __UVISOR_API_REGISTER_GATEWAY_H__
00018 #define __UVISOR_API_REGISTER_GATEWAY_H__
00019 
00020 #include "api/inc/register_gateway_exports.h"
00021 #include "api/inc/uvisor_exports.h"
00022 #include <stdint.h>
00023 
00024 /** Get the offset of a struct member.
00025  * @internal
00026  */
00027 #define __UVISOR_OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member)))
00028 
00029 /** Generate the opcode of the 16-bit Thumb-2 16-bit T2 encoding of the branch
00030  *  instruction.
00031  * @internal
00032  * @note The branch instruction is encoded according to the Thumb-2 immediate
00033  * encoding rules:
00034  *     <instr_addr>: B.N <label>
00035  *     imm = (<label>_addr - PC) / 2
00036  * Where:
00037  *     PC = <instr>_addr + 4
00038  * The +4 is to account for the pipelined PC at the time of the branch
00039  * instruction. See ARM DDI 0403E.b page A4-102 for more details.
00040  * @param instr[in] Address of the branch instruction
00041  * @param label[in] Address of the label
00042  * @returns the 16-bit encoding of the B.N <label> instruction.
00043  */
00044 #define BRANCH_OPCODE(instr, label) \
00045     (uint16_t) (0xE000 | (uint8_t) ((((uint32_t) (label) - ((uint32_t) (instr) + 4)) / 2) & 0xFF))
00046 
00047 /** `BX LR` encoding
00048  * @internal
00049  */
00050 #define BXLR                           ((uint16_t) 0x4770)
00051 
00052 /** Register Gateway - Read operation
00053  *
00054  * This macro provides an API to perform 32-bit read operations on restricted
00055  * registers. Such accesses are assembled into a read-only flash structure that
00056  * is read and validated by uVisor before performing the operation.
00057  *
00058  * @warning This API currently only supports link-time known value for the
00059  * address, operation and mask.
00060  *
00061  * @param box_name[in]  The name of the source box as decalred in
00062  *                      `UVISOR_BOX_CONFIG`.
00063  * @param shared[in]    Whether the gateway can be shared with other boxes or
00064  *                      not. Two values are available: UVISOR_RGW_SHARED,
00065  *                      UVISOR_RGW_EXCLUSIVE.
00066  * @param addr[in]      The address for the data access.
00067  * @param operation[in] The operation to perform at the address for the read. It
00068  *                      is chosen among the `UVISOR_RGW_OP_*` macros.
00069  * @param mask[in]      The mask to apply for the read operation.
00070  * @returns The value read from address using the operation and mask provided
00071  * (or their respective defaults if they have not been provided).
00072  */
00073 #define uvisor_read(box_name, shared, addr, op, msk) \
00074     ({ \
00075         /* Instanstiate the gateway. This gets resolved at link-time. */ \
00076         UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \
00077             .svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
00078             .branch     = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
00079                                         __UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
00080             .magic      = UVISOR_REGISTER_GATEWAY_MAGIC, \
00081             .box_ptr    = (uint32_t) & box_name ## _cfg_ptr, \
00082             .address    = (uint32_t) addr, \
00083             .mask       = msk, \
00084             .operation  = UVISOR_RGW_OP(op, sizeof(*addr), shared), \
00085             .bxlr       = BXLR  \
00086         }; \
00087         \
00088         /* Pointer to the register gateway we just created. The pointer is
00089          * located in a discoverable linker section. */ \
00090         __attribute__((section(".keep.uvisor.register_gateway_ptr"))) \
00091         static uint32_t const register_gateway_ptr = (uint32_t) &register_gateway; \
00092         (void) register_gateway_ptr; \
00093         \
00094         /* Call the actual gateway. */ \
00095         uint32_t result = ((uint32_t (*)(void)) ((uint32_t) &register_gateway | 1))(); \
00096         (typeof(*addr)) result; \
00097     })
00098 
00099 /** Register Gateway - Write operation
00100  *
00101  * This macro provides an API to perform 32-bit write operations on restricted
00102  * registers. Such accesses are assembled into a read-only flash structure that
00103  * is read and validated by uVisor before performing the operation.
00104  *
00105  * @warning This API currently only supports link-time known value for the
00106  * address, operation and mask.
00107  *
00108  * @param box_name[in]  The name of the source box as decalred in
00109  *                      `UVISOR_BOX_CONFIG`.
00110  * @param shared[in]    Whether the gateway can be shared with other boxes or
00111  *                      not. Two values are available: UVISOR_RGW_SHARED,
00112  *                      UVISOR_RGW_EXCLUSIVE.
00113  * @param addr[in]      The address for the data access.
00114  * @param val[in]       The value to write at address.
00115  * @param operation[in] The operation to perform at the address for the read. It
00116  *                      is chosen among the `UVISOR_RGW_OP_*` macros.
00117  * @param mask[in]      The mask to apply for the write operation.
00118  */
00119 #define uvisor_write(box_name, shared, addr, val, op, msk) \
00120     { \
00121         /* Instanstiate the gateway. This gets resolved at link-time. */ \
00122         UVISOR_ALIGN(4) static TRegisterGateway const register_gateway = { \
00123             .svc_opcode = UVISOR_SVC_OPCODE(UVISOR_SVC_ID_REGISTER_GATEWAY), \
00124             .branch     = BRANCH_OPCODE(__UVISOR_OFFSETOF(TRegisterGateway, branch), \
00125                                         __UVISOR_OFFSETOF(TRegisterGateway, bxlr)), \
00126             .magic      = UVISOR_REGISTER_GATEWAY_MAGIC, \
00127             .box_ptr    = (uint32_t) & box_name ## _cfg_ptr, \
00128             .address    = (uint32_t) addr, \
00129             .mask       = msk, \
00130             .operation  = UVISOR_RGW_OP(op, sizeof(*addr), shared), \
00131             .bxlr       = BXLR  \
00132         }; \
00133         \
00134         /* Pointer to the register gateway we just created. The pointer is
00135          * located in a discoverable linker section. */ \
00136         __attribute__((section(".keep.uvisor.register_gateway_ptr"))) \
00137         static uint32_t const register_gateway_ptr = (uint32_t) &register_gateway; \
00138         (void) register_gateway_ptr; \
00139         \
00140         /* Call the actual gateway.
00141          * The value is passed as the first argument. */ \
00142         ((void (*)(uint32_t)) ((uint32_t) ((uint32_t) &register_gateway | 1)))((uint32_t) (val)); \
00143     }
00144 
00145 /** Get the selected bits at the target address.
00146  * @param box_name[in] Box name as defined by the uVisor box configuration
00147  *                     macro `UVISOR_BOX_CONFIG`
00148  * @param shared[in]   Whether the gateway can be shared with other boxes or
00149  *                     not. Two values are available: UVISOR_RGW_SHARED,
00150  *                     UVISOR_RGW_EXCLUSIVE.
00151  * @param address[in]  Target address
00152  * @param mask[in]     Bits to select out of the target address
00153  * @returns The value `*address & mask`.
00154  */
00155 #define UVISOR_BITS_GET(box_name, shared, address, mask) \
00156     /* Register gateway implementation:
00157      * *address & mask */ \
00158     uvisor_read(box_name, shared, address, UVISOR_RGW_OP_READ_AND, mask)
00159 
00160 /** Check the selected bits at the target address.
00161  * @param box_name[in] Box name as defined by the uVisor box configuration
00162  *                     macro `UVISOR_BOX_CONFIG`
00163  * @param shared[in]   Whether the gateway can be shared with other boxes or
00164  *                     not. Two values are available: UVISOR_RGW_SHARED,
00165  *                     UVISOR_RGW_EXCLUSIVE.
00166  * @param address[in]  Address at which to check the bits
00167  * @param mask[in]     Bits to select out of the target address
00168  * @returns The value `((*address & mask) == mask)`.
00169  */
00170 #define UVISOR_BITS_CHECK(box_name, shared, address, mask) \
00171     ((UVISOR_BITS_GET(box_name, shared, address, mask)) == (mask))
00172 
00173 /** Set the selected bits to 1 at the target address.
00174  *
00175  * Equivalent to: `*address |= mask`.
00176  * @param box_name[in] Box name as defined by the uVisor box configuration
00177  *                     macro `UVISOR_BOX_CONFIG`
00178  * @param shared[in]   Whether the gateway can be shared with other boxes or
00179  *                     not. Two values are available: UVISOR_RGW_SHARED,
00180  *                     UVISOR_RGW_EXCLUSIVE.
00181  * @param address[in]  Target address
00182  * @param mask[in]     Bits to select out of the target address
00183  */
00184 #define UVISOR_BITS_SET(box_name, shared, address, mask) \
00185     /* Register gateway implementation:
00186      * *address |= (mask & mask) */ \
00187     uvisor_write(box_name, shared, address, mask, UVISOR_RGW_OP_WRITE_OR, mask)
00188 
00189 /** Clear the selected bits at the target address.
00190  *
00191  * Equivalent to: `*address &= ~mask`.
00192  * @param box_name[in] Box name as defined by the uVisor box configuration
00193  *                     macro `UVISOR_BOX_CONFIG`
00194  * @param shared[in]   Whether the gateway can be shared with other boxes or
00195  *                     not. Two values are available: UVISOR_RGW_SHARED,
00196  *                     UVISOR_RGW_EXCLUSIVE.
00197  * @param address[in]  Target address
00198  * @param mask[in]     Bits to select out of the target address
00199  */
00200 #define UVISOR_BITS_CLEAR(box_name, shared, address, mask) \
00201     /* Register gateway implementation:
00202      * *address &= (0x00000000 | ~mask) */ \
00203     uvisor_write(box_name, shared, address, 0x00000000, UVISOR_RGW_OP_WRITE_AND, mask)
00204 
00205 /** Set the selected bits at the target address to the given value.
00206  *
00207  * Equivalent to: `*address = (*address & ~mask) | (value & mask)`.
00208  * @param box_name[in] Box name as defined by the uVisor box configuration
00209  *                     macro `UVISOR_BOX_CONFIG`
00210  * @param shared[in]   Whether the gateway can be shared with other boxes or
00211  *                     not. Two values are available: UVISOR_RGW_SHARED,
00212  *                     UVISOR_RGW_EXCLUSIVE.
00213  * @param address[in]  Target address
00214  * @param mask[in]     Bits to select out of the target address
00215  * @param value[in]    Value to write at the address location. Note: The value
00216  *                     must be already shifted to the correct bit position
00217  */
00218 #define UVISOR_BITS_SET_VALUE(box_name, shared, address, mask, value) \
00219     /* Register gateway implementation:
00220      * *address = (*address & ~mask) | (value & mask) */ \
00221     uvisor_write(box_name, shared, address, value, UVISOR_RGW_OP_WRITE_REPLACE, mask)
00222 
00223 /** Toggle the selected bits at the target address.
00224  *
00225  * Equivalent to: `*address ^= mask`.
00226  * @param box_name[in] Box name as defined by the uVisor box configuration
00227  *                     macro `UVISOR_BOX_CONFIG`
00228  * @param shared[in]   Whether the gateway can be shared with other boxes or
00229  *                     not. Two values are available: UVISOR_RGW_SHARED,
00230  *                     UVISOR_RGW_EXCLUSIVE.
00231  * @param address[in]  Target address
00232  * @param mask[in]     Bits to select out of the target address
00233  */
00234 #define UVISOR_BITS_TOGGLE(box_name, shared, address, mask) \
00235     /* Register gateway implementation:
00236      * *address ^= (0xFFFFFFFF & mask) */ \
00237     uvisor_write(box_name, shared, address, 0xFFFFFFFF, UVISOR_RGW_OP_WRITE_XOR, mask)
00238 
00239 #endif /* __UVISOR_API_REGISTER_GATEWAY_H__ */