nkjnm

Dependencies:   MAX44000 nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Committer:
nitsshukla
Date:
Fri Nov 04 12:06:04 2016 +0000
Revision:
7:3a65ef12ba31
Parent:
1:55a6170b404f
kghj;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nexpaq 1:55a6170b404f 1 # Quick-Start Guide for uVisor on mbed OS
nexpaq 1:55a6170b404f 2
nexpaq 1:55a6170b404f 3 This guide will help you get started with uVisor on mbed OS by walking you through creating a sample application for the NXP FRDM-K64F board.
nexpaq 1:55a6170b404f 4
nexpaq 1:55a6170b404f 5 The uVisor provides sandboxed environments and resources protection for applications built for ARM Cortex-M3 and Cortex-M4 devices. Here we will show you how to enable the uVisor and configure a secure box to get hold of some exclusive resources (memory, peripherals, interrupts). For more information on the uVisor design philosophy, please check out our the uVisor [introductory document](../../README.md).
nexpaq 1:55a6170b404f 6
nexpaq 1:55a6170b404f 7 ## Overview
nexpaq 1:55a6170b404f 8
nexpaq 1:55a6170b404f 9 To get a basic `blinky` application running on mbed OS with uVisor enabled, you will need the following:
nexpaq 1:55a6170b404f 10
nexpaq 1:55a6170b404f 11 * A platform and a toolchain supported by uVisor on mbed OS. You can verify this on [the official list](../../README.md#supported-platforms). Please note that uVisor might support some platform internally, but not on mbed OS. Generally this means that the porting process has only been partially completed. If you want to port your platform to uVisor and enable it on mbed OS, please follow the [uVisor Porting Guide for mbed OS](../core/PORTING.md).
nexpaq 1:55a6170b404f 12 * git. It will be used to download the mbed codebase.
nexpaq 1:55a6170b404f 13 * The mbed command-line tools, mbed-cli. You can run `pip install mbed-cli` to install them.
nexpaq 1:55a6170b404f 14
nexpaq 1:55a6170b404f 15 For the remainder of this guide we will assume the following:
nexpaq 1:55a6170b404f 16
nexpaq 1:55a6170b404f 17 * You are developing on a \*nix machine, in the `~/code` folder.
nexpaq 1:55a6170b404f 18 * You are building the app for the [NXP FRDM-K64F](http://developer.mbed.org/platforms/FRDM-K64F/) target, with the [GCC ARM Embedded](https://launchpad.net/gcc-arm-embedded) toolchain.
nexpaq 1:55a6170b404f 19
nexpaq 1:55a6170b404f 20 The instructions provided can be easily generalized to the case of other targets on other host OSs.
nexpaq 1:55a6170b404f 21
nexpaq 1:55a6170b404f 22 ## Start with the `blinky` app
nexpaq 1:55a6170b404f 23 [Go to top](#overview)
nexpaq 1:55a6170b404f 24
nexpaq 1:55a6170b404f 25 To create a new mbed application called `uvisor-example` just run the following commands:
nexpaq 1:55a6170b404f 26
nexpaq 1:55a6170b404f 27 ```bash
nexpaq 1:55a6170b404f 28 $ cd ~/code
nexpaq 1:55a6170b404f 29 $ mbed new uvisor-example
nexpaq 1:55a6170b404f 30 ```
nexpaq 1:55a6170b404f 31
nexpaq 1:55a6170b404f 32 The mbed-cli tools will automatically fetch the mbed codebase for you. By default, git will be used to track your code changes, so your application will be ready to be pushed to a git server, if you want to.
nexpaq 1:55a6170b404f 33
nexpaq 1:55a6170b404f 34 Once the import process is finished, create a `source` folder:
nexpaq 1:55a6170b404f 35 ```bash
nexpaq 1:55a6170b404f 36 $ mkdir ~/code/uvisor-example/source
nexpaq 1:55a6170b404f 37 ```
nexpaq 1:55a6170b404f 38 and place a new file `main.cpp` in it:
nexpaq 1:55a6170b404f 39
nexpaq 1:55a6170b404f 40 ```C
nexpaq 1:55a6170b404f 41 /* ~/code/uvisor-example/source/main.cpp */
nexpaq 1:55a6170b404f 42
nexpaq 1:55a6170b404f 43 #include "mbed.h"
nexpaq 1:55a6170b404f 44 #include "rtos.h"
nexpaq 1:55a6170b404f 45
nexpaq 1:55a6170b404f 46 DigitalOut led(LED1);
nexpaq 1:55a6170b404f 47
nexpaq 1:55a6170b404f 48 int main(void)
nexpaq 1:55a6170b404f 49 {
nexpaq 1:55a6170b404f 50 while (true) {
nexpaq 1:55a6170b404f 51 led = !led;
nexpaq 1:55a6170b404f 52 Thread::wait(500);
nexpaq 1:55a6170b404f 53 }
nexpaq 1:55a6170b404f 54 }
nexpaq 1:55a6170b404f 55 ```
nexpaq 1:55a6170b404f 56
nexpaq 1:55a6170b404f 57 This simple application just blinks an LED from the main thread, which is created by default by the OS.
nexpaq 1:55a6170b404f 58
nexpaq 1:55a6170b404f 59 ---
nexpaq 1:55a6170b404f 60
nexpaq 1:55a6170b404f 61 **Checkpoint**
nexpaq 1:55a6170b404f 62
nexpaq 1:55a6170b404f 63 Compile the application:
nexpaq 1:55a6170b404f 64
nexpaq 1:55a6170b404f 65 ```bash
nexpaq 1:55a6170b404f 66 $ mbed compile -m K64F -t GCC_ARM
nexpaq 1:55a6170b404f 67 ```
nexpaq 1:55a6170b404f 68
nexpaq 1:55a6170b404f 69 The resulting binary will be located at:
nexpaq 1:55a6170b404f 70
nexpaq 1:55a6170b404f 71 ```bash
nexpaq 1:55a6170b404f 72 ~/code/uvisor-example/.build/K64F/GCC_ARM/uvisor-example.bin
nexpaq 1:55a6170b404f 73 ```
nexpaq 1:55a6170b404f 74
nexpaq 1:55a6170b404f 75 Drag-and-drop it onto the USB device mounted on your computer in order to flash the device. When the flashing process is completed, press the reset button on the device. You should see the device LED blinking.
nexpaq 1:55a6170b404f 76
nexpaq 1:55a6170b404f 77 ---
nexpaq 1:55a6170b404f 78
nexpaq 1:55a6170b404f 79 In the next sections you will see:
nexpaq 1:55a6170b404f 80
nexpaq 1:55a6170b404f 81 * How to [enable uVisor](#enable-uvisor) on the `uvisor-example` app.
nexpaq 1:55a6170b404f 82 * How to [add a secure box](#add-a-secure-box) to the `uvisor-example` app with exclusive access to a timer, to a push-button interrupt, and to static and dynamic memories.
nexpaq 1:55a6170b404f 83
nexpaq 1:55a6170b404f 84 ## Enable uVisor
nexpaq 1:55a6170b404f 85 [Go to top](#overview)
nexpaq 1:55a6170b404f 86
nexpaq 1:55a6170b404f 87 To enable the uVisor on the app, just add the following lines at the beginning of the `main.cpp` file:
nexpaq 1:55a6170b404f 88
nexpaq 1:55a6170b404f 89 ```C
nexpaq 1:55a6170b404f 90 /* ~/code/uvisor-example/source/main.cpp */
nexpaq 1:55a6170b404f 91
nexpaq 1:55a6170b404f 92 #include "mbed.h"
nexpaq 1:55a6170b404f 93 #include "rtos.h"
nexpaq 1:55a6170b404f 94 #include "uvisor-lib/uvisor-lib.h"
nexpaq 1:55a6170b404f 95
nexpaq 1:55a6170b404f 96 /* Register privleged system IRQ hooks.
nexpaq 1:55a6170b404f 97 * This is a system-wide configuration and it is independent from the app, but
nexpaq 1:55a6170b404f 98 * for the moment it needs to be specified in the app. This will change in a
nexpaq 1:55a6170b404f 99 * later version: The configuration will be provided by the OS. */
nexpaq 1:55a6170b404f 100 extern "C" void SVC_Handler(void);
nexpaq 1:55a6170b404f 101 extern "C" void PendSV_Handler(void);
nexpaq 1:55a6170b404f 102 extern "C" void SysTick_Handler(void);
nexpaq 1:55a6170b404f 103 UVISOR_SET_PRIV_SYS_IRQ_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler);
nexpaq 1:55a6170b404f 104
nexpaq 1:55a6170b404f 105 /* Main box Access Control Lists (ACLs). */
nexpaq 1:55a6170b404f 106 /* Note: These are specific to the NXP FRDM-K64F board. See the section below
nexpaq 1:55a6170b404f 107 * for more information. */
nexpaq 1:55a6170b404f 108 static const UvisorBoxAclItem g_main_box_acls[] = {
nexpaq 1:55a6170b404f 109 /* For the LED */
nexpaq 1:55a6170b404f 110 {SIM, sizeof(*SIM), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 111 {PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 112
nexpaq 1:55a6170b404f 113 /* For messages printed on the serial port. */
nexpaq 1:55a6170b404f 114 {OSC, sizeof(*OSC), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 115 {MCG, sizeof(*MCG), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 116 {UART0, sizeof(*UART0), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 117 };
nexpaq 1:55a6170b404f 118
nexpaq 1:55a6170b404f 119 /* Enable uVisor, using the ACLs we just created. */
nexpaq 1:55a6170b404f 120 UVISOR_SET_MODE_ACL(UVISOR_ENABLED, g_main_box_acls);
nexpaq 1:55a6170b404f 121
nexpaq 1:55a6170b404f 122 /* Rest of the existing app code */
nexpaq 1:55a6170b404f 123 ...
nexpaq 1:55a6170b404f 124 ```
nexpaq 1:55a6170b404f 125
nexpaq 1:55a6170b404f 126 In the code above we specified 3 elements:
nexpaq 1:55a6170b404f 127
nexpaq 1:55a6170b404f 128 1. System-wide uVisor configurations: `UVISOR_SET_PRIV_SYS_IRQ_HOOKS`. Application authors currently need to specify the privileged system IRQ hooks at the application level with this macro, but in the future the operating system will register the privileged system IRQ hooks on its own.
nexpaq 1:55a6170b404f 129 1. Main box Access Control Lists (ACLs). Since with uVisor enabled everything runs in unprivileged mode, we need to make sure that peripherals that are accessed by the OS and the main box are allowed. These peripherals are specified using a list like the one in the snippet above. For the purpose of this example we provide you the list of all the ACLs that we know you will need. For other platforms or other applications you need to determine those ACLs following a process that is described in a [section](#the-main-box-acls) below.
nexpaq 1:55a6170b404f 130 1. App-specific uVisor configurations: `UVISOR_SET_MODE_ACL`. This macro sets the uVisor mode (enabled) and associates the list of ACLs we just created with the main box.
nexpaq 1:55a6170b404f 131
nexpaq 1:55a6170b404f 132 Before compiling, we need to override the original `K64F` target to enable the uVisor feature. To do so, add the file `~/code/uvisor-example/mbed_app.json` with the following content:
nexpaq 1:55a6170b404f 133
nexpaq 1:55a6170b404f 134 ```JSON
nexpaq 1:55a6170b404f 135 {
nexpaq 1:55a6170b404f 136 "target_overrides": {
nexpaq 1:55a6170b404f 137 "K64F": {
nexpaq 1:55a6170b404f 138 "target.features_add": ["UVISOR"],
nexpaq 1:55a6170b404f 139 "target.extra_labels_add": ["UVISOR_SUPPORTED"]
nexpaq 1:55a6170b404f 140 }
nexpaq 1:55a6170b404f 141 },
nexpaq 1:55a6170b404f 142 "macros": [
nexpaq 1:55a6170b404f 143 "FEATURE_UVISOR",
nexpaq 1:55a6170b404f 144 "TARGET_UVISOR_SUPPORTED"
nexpaq 1:55a6170b404f 145 ]
nexpaq 1:55a6170b404f 146 }
nexpaq 1:55a6170b404f 147 ```
nexpaq 1:55a6170b404f 148
nexpaq 1:55a6170b404f 149 The macros `FEATURE_UVISOR` and `TARGET_UVISOR_SUPPORTED` in the configuration file above are automatically defined for C and C++ files, but not for assembly files. Since the uVisor relies on those symbols in some assembly code, we need to define them manually.
nexpaq 1:55a6170b404f 150
nexpaq 1:55a6170b404f 151 ---
nexpaq 1:55a6170b404f 152
nexpaq 1:55a6170b404f 153 **Checkpoint**
nexpaq 1:55a6170b404f 154
nexpaq 1:55a6170b404f 155 Compile the application again. This time the `K64F` target will include the new features and labels we provided in `mbed_app.json`;
nexpaq 1:55a6170b404f 156
nexpaq 1:55a6170b404f 157 ```bash
nexpaq 1:55a6170b404f 158 $ mbed compile -m K64F -t GCC_ARM
nexpaq 1:55a6170b404f 159 ```
nexpaq 1:55a6170b404f 160
nexpaq 1:55a6170b404f 161 The binary will be located at:
nexpaq 1:55a6170b404f 162
nexpaq 1:55a6170b404f 163 ```bash
nexpaq 1:55a6170b404f 164 ~/code/uvisor-example/.build/K64F/GCC_ARM/uvisor-example.bin
nexpaq 1:55a6170b404f 165 ```
nexpaq 1:55a6170b404f 166
nexpaq 1:55a6170b404f 167 Re-flash the device and press the reset button. The device LED should be blinking as in the previous case.
nexpaq 1:55a6170b404f 168
nexpaq 1:55a6170b404f 169 ---
nexpaq 1:55a6170b404f 170
nexpaq 1:55a6170b404f 171 If you enable uVisor in the `blinky` app as it was written above, you will not get any particular security feature. All code and resources share the same security context, which we call the *main box*.
nexpaq 1:55a6170b404f 172
nexpaq 1:55a6170b404f 173 A lot happens under the hood, though. All the user code now runs in unprivileged mode, and the systems services like the `NVIC` APIs or the OS SVCalls are routed through the uVisor.
nexpaq 1:55a6170b404f 174
nexpaq 1:55a6170b404f 175 ## Add a secure box
nexpaq 1:55a6170b404f 176 [Go to top](#overview)
nexpaq 1:55a6170b404f 177
nexpaq 1:55a6170b404f 178 Now that uVisor is enabled, we can finally add a *secure box*.
nexpaq 1:55a6170b404f 179
nexpaq 1:55a6170b404f 180 A secure box is a special compartment that is granted exclusive access to peripherals, memories and interrupts. Private resources are only accessible when the *context* of the secure box is active. The uVisor is the only one that can enable a secure box context, for example upon thread switching or interrupt handling.
nexpaq 1:55a6170b404f 181
nexpaq 1:55a6170b404f 182 Code that belongs to a box is not obfuscated by uVisor, so it is still readable and executable from outside of the box. In addition, declaring an object in the same file that configures a secure box does not protect that object automatically.
nexpaq 1:55a6170b404f 183
nexpaq 1:55a6170b404f 184 Instead, we provide specific APIs to instruct the uVisor to protect a private resource. Here we will show how to use these APIs in the `uvisor-example` app.
nexpaq 1:55a6170b404f 185
nexpaq 1:55a6170b404f 186 ### Configure the secure box
nexpaq 1:55a6170b404f 187
nexpaq 1:55a6170b404f 188 For this example, we want to create a secure box called `private_timer`. The `private_timer` box will be configured to have exclusive access to the PIT timer and to the GPIO PORT C on the NXP FRDM-K64F board, which means that other boxes will be prevented from accessing these peripherals.
nexpaq 1:55a6170b404f 189
nexpaq 1:55a6170b404f 190 Each secure box must have at least one thread, which we call the box's main thread. In our `private_timer` box we will only use this thread throughout the whole program. The thread will constantly save the current timer value in a private buffer. In addition, we want to print the content of the buffered timer values whenever we press the `SW2` button on the board.
nexpaq 1:55a6170b404f 191
nexpaq 1:55a6170b404f 192 We want the box to have exclusive access to the following resources:
nexpaq 1:55a6170b404f 193
nexpaq 1:55a6170b404f 194 * The timer and push-button peripherals (as specified by a peripheral ACL). Nobody else should be able to read the timer values.
nexpaq 1:55a6170b404f 195 * The push-button interrupt (as specified by an IRQ ACL). We want the button IRQ to be re-routed to our box-specific ISR.
nexpaq 1:55a6170b404f 196 * The buffer that holds the timer samples (as specified by a dynamic memory ACL).
nexpaq 1:55a6170b404f 197 * The static memory that holds information about the timer buffer (as specified by a static memory ACL).
nexpaq 1:55a6170b404f 198
nexpaq 1:55a6170b404f 199 Create a new source file, `~/code/uvisor-example/source/secure_box.cpp`. We will configure the secure box inside this file. The secure box name for this example is `private_timer`.
nexpaq 1:55a6170b404f 200
nexpaq 1:55a6170b404f 201 ```C
nexpaq 1:55a6170b404f 202 /* ~/code/uvisor-example/source/secure_box.cpp */
nexpaq 1:55a6170b404f 203
nexpaq 1:55a6170b404f 204 #include "mbed.h"
nexpaq 1:55a6170b404f 205 #include "rtos.h"
nexpaq 1:55a6170b404f 206 #include "uvisor-lib/uvisor-lib.h"
nexpaq 1:55a6170b404f 207
nexpaq 1:55a6170b404f 208 /* Private static memory for the secure box */
nexpaq 1:55a6170b404f 209 typedef struct {
nexpaq 1:55a6170b404f 210 uint32_t * buffer;
nexpaq 1:55a6170b404f 211 int index;
nexpaq 1:55a6170b404f 212 } PrivateTimerStaticMemory;
nexpaq 1:55a6170b404f 213
nexpaq 1:55a6170b404f 214 /* ACLs list for the secure box: Timer (PIT). */
nexpaq 1:55a6170b404f 215 static const UvisorBoxAclItem g_private_timer_acls[] = {
nexpaq 1:55a6170b404f 216 {PIT, sizeof(*PIT), UVISOR_TACLDEF_PERIPH}
nexpaq 1:55a6170b404f 217 {PORTC, sizeof(*PORTC), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 218 };
nexpaq 1:55a6170b404f 219
nexpaq 1:55a6170b404f 220 static void private_timer_main_thread(const void *);
nexpaq 1:55a6170b404f 221
nexpaq 1:55a6170b404f 222 /* Secure box configuration */
nexpaq 1:55a6170b404f 223 UVISOR_BOX_NAMESPACE(NULL); /* We won't specify a box namespace for this example. */
nexpaq 1:55a6170b404f 224 UVISOR_BOX_HEAPSIZE(4096); /* Heap size for the secure box */
nexpaq 1:55a6170b404f 225 UVISOR_BOX_MAIN(private_timer_main_thread, /* Main thread for the secure box */
nexpaq 1:55a6170b404f 226 osPriorityNormal, /* Priority of the secure box's main thread */
nexpaq 1:55a6170b404f 227 1024); /* Stack size for the secure box's main thread */
nexpaq 1:55a6170b404f 228 UVISOR_BOX_CONFIG(private_timer, /* Name of the secure box */
nexpaq 1:55a6170b404f 229 g_private_timer_acls, /* ACLs list for the secure box */
nexpaq 1:55a6170b404f 230 1024, /* Stack size for the secure box */
nexpaq 1:55a6170b404f 231 PrivateTimerStaticMemory); /* Private static memory for the secure box. */
nexpaq 1:55a6170b404f 232 ```
nexpaq 1:55a6170b404f 233
nexpaq 1:55a6170b404f 234 ### Create the secure box's main thread function
nexpaq 1:55a6170b404f 235
nexpaq 1:55a6170b404f 236 In general, you can decide what to do in your box's main thread. You can run it once and then kill it, use it to configure memories, peripherals, or to create other threads. In this app, the box's main thread is the only thread for the `private_timer` box, and it will run throughout the whole program.
nexpaq 1:55a6170b404f 237
nexpaq 1:55a6170b404f 238 The `private_timer_main_thread` function configures the PIT timer, allocates the dynamic buffer to hold the timer values and initializes its private static memory, `PrivateTimerStaticMemory`. A spinning loop is used to update the values in the buffer every time the thread is reactivated.
nexpaq 1:55a6170b404f 239
nexpaq 1:55a6170b404f 240 ```C
nexpaq 1:55a6170b404f 241 /* Number of timer samples we will use */
nexpaq 1:55a6170b404f 242 #define PRIVATE_TIMER_BUFFER_COUNT 256
nexpaq 1:55a6170b404f 243
nexpaq 1:55a6170b404f 244 /* For debug purposes: print the buffer values when the SW2 button is pressed. */
nexpaq 1:55a6170b404f 245 static void private_timer_button_on_press(void)
nexpaq 1:55a6170b404f 246 {
nexpaq 1:55a6170b404f 247 for (int i = 0; i < PRIVATE_TIMER_BUFFER_COUNT; i++) {
nexpaq 1:55a6170b404f 248 printf("buffer[%03d] = %lu\r\n", i, uvisor_ctx->buffer[i]);
nexpaq 1:55a6170b404f 249 }
nexpaq 1:55a6170b404f 250 }
nexpaq 1:55a6170b404f 251
nexpaq 1:55a6170b404f 252 /* Main thread for the secure box */
nexpaq 1:55a6170b404f 253 static void private_timer_main_thread(const void *)
nexpaq 1:55a6170b404f 254 {
nexpaq 1:55a6170b404f 255 /* Create the buffer and cache its pointer to the private static memory. */
nexpaq 1:55a6170b404f 256 uvisor_ctx->buffer = (uint32_t *) malloc(PRIVATE_TIMER_BUFFER_COUNT * sizeof(uint32_t));
nexpaq 1:55a6170b404f 257 if (uvisor_ctx->buffer == NULL) {
nexpaq 1:55a6170b404f 258 mbed_die();
nexpaq 1:55a6170b404f 259 }
nexpaq 1:55a6170b404f 260 uvisor_ctx->index = 0;
nexpaq 1:55a6170b404f 261
nexpaq 1:55a6170b404f 262 /* Setup the push-button callback. */
nexpaq 1:55a6170b404f 263 InterruptIn button(SW2);
nexpaq 1:55a6170b404f 264 button.mode(PullUp);
nexpaq 1:55a6170b404f 265 button.fall(&private_timer_button_on_press);
nexpaq 1:55a6170b404f 266
nexpaq 1:55a6170b404f 267 /* Setup and start the timer. */
nexpaq 1:55a6170b404f 268 Timer timer;
nexpaq 1:55a6170b404f 269 timer.start();
nexpaq 1:55a6170b404f 270
nexpaq 1:55a6170b404f 271 while (1) {
nexpaq 1:55a6170b404f 272 /* Store the timer value. */
nexpaq 1:55a6170b404f 273 uvisor_ctx->buffer[uvisor_ctx->index] = timer.read_us();
nexpaq 1:55a6170b404f 274
nexpaq 1:55a6170b404f 275 /* Update the index. Behave as a circular buffer. */
nexpaq 1:55a6170b404f 276 if (uvisor_ctx->index < PRIVATE_TIMER_BUFFER_COUNT - 1) {
nexpaq 1:55a6170b404f 277 uvisor_ctx->index++;
nexpaq 1:55a6170b404f 278 } else {
nexpaq 1:55a6170b404f 279 uvisor_ctx->index = 0;
nexpaq 1:55a6170b404f 280 }
nexpaq 1:55a6170b404f 281 }
nexpaq 1:55a6170b404f 282 }
nexpaq 1:55a6170b404f 283 ```
nexpaq 1:55a6170b404f 284
nexpaq 1:55a6170b404f 285 A few things to note in the code above:
nexpaq 1:55a6170b404f 286
nexpaq 1:55a6170b404f 287 * If code is running in the context of `private_timer`, then any object instantiated inside that code will belong to the `private_timer` heap and stack. This means that in the example above the `InterruptIn` and `Timer` objects are private to the `private_timer` box. The same applies to the dynamically allocated buffer `uvisor_ctx->buffer`.
nexpaq 1:55a6170b404f 288 * The content of the private memory `PrivateTimerStaticMemory` can be accessed using the `PrivateTimerStaticMemory * uvisor_ctx` pointer, which is maintained by uVisor.
nexpaq 1:55a6170b404f 289 * The `InterruptIn` object triggers the registration of an interrupt slot. Since that code is run in the context of the `private_timer` box, then the push-button IRQ belongs to that box. If you want to use the IRQ APIs directly, read the [section](#the-nvic-apis) below.
nexpaq 1:55a6170b404f 290 * Even if the `private_timer_button_on_press` function runs in the context of `private_timer`, we can still use the `printf` function, which accesses the `UART0` peripheral, owned by the main box. This is because all ACLs declared in the main box are by default shared with all the other secure boxes. This also means that the messages we are printing on the serial port are not secure, because other boxes have access to that peripheral.
nexpaq 1:55a6170b404f 291
nexpaq 1:55a6170b404f 292 > **Warning**: Instantiating an object in the `secure_box.cpp` global scope will automatically map it to the main box context, not the `private_timer` one. If you want an object to be private to a box, you need to instantiate it inside the code that will run in the context of that box (like the `InterruptIn` and `Timer` objects), or alternatively statically initialize it in the box private static memory (like the `buffer` and `index` variables in `PrivateTimerStaticMemory`).
nexpaq 1:55a6170b404f 293
nexpaq 1:55a6170b404f 294 ---
nexpaq 1:55a6170b404f 295
nexpaq 1:55a6170b404f 296 **Checkpoint**
nexpaq 1:55a6170b404f 297
nexpaq 1:55a6170b404f 298 Compile the application again:
nexpaq 1:55a6170b404f 299
nexpaq 1:55a6170b404f 300 ```bash
nexpaq 1:55a6170b404f 301 $ mbed compile -m K64F -t GCC_ARM
nexpaq 1:55a6170b404f 302 ```
nexpaq 1:55a6170b404f 303
nexpaq 1:55a6170b404f 304 Re-flash the device, and press the reset button. The device LED should be blinking as in the previous case.
nexpaq 1:55a6170b404f 305
nexpaq 1:55a6170b404f 306 If you don't see the LED blinking, it means that the application halted somewhere, probably because uVisor captured a fault. You can setup the uVisor debug messages to see if there is any problem. Follow the [Debugging uVisor on mbed OS](DEBUGGING.md) document for a step-by-step guide.
nexpaq 1:55a6170b404f 307
nexpaq 1:55a6170b404f 308 If the LED is blinking, it means that the app is running fine. If you now press the `SW2` button on the NXP FRDM-K64F board, the `private_timer_button_on_press` function will be executed, printing the values in the timer buffer. You can observe these values by opening a serial port connection to the device, with a baud rate of 9600. When the print is completed, you should see the LED blinking again.
nexpaq 1:55a6170b404f 309
nexpaq 1:55a6170b404f 310 ### Expose public secure entry points to the secure box
nexpaq 1:55a6170b404f 311
nexpaq 1:55a6170b404f 312 Coming soon.
nexpaq 1:55a6170b404f 313
nexpaq 1:55a6170b404f 314 ## Wrap-up
nexpaq 1:55a6170b404f 315 [Go to top](#overview)
nexpaq 1:55a6170b404f 316
nexpaq 1:55a6170b404f 317 In this guide we showed you how to:
nexpaq 1:55a6170b404f 318
nexpaq 1:55a6170b404f 319 * Enable uVisor on an existing application.
nexpaq 1:55a6170b404f 320 * Add a secure box to your application.
nexpaq 1:55a6170b404f 321 * Protect static and dynamic memories in a secure box.
nexpaq 1:55a6170b404f 322 * Gain exclusive access to a peripheral and an IRQ in a secure box.
nexpaq 1:55a6170b404f 323 * (Coming soon) Expose public secure entry points to a secure box.
nexpaq 1:55a6170b404f 324
nexpaq 1:55a6170b404f 325 You can now modify the example or create a new one to protect your resources into a secure box. You might find the following resources useful:
nexpaq 1:55a6170b404f 326
nexpaq 1:55a6170b404f 327 * [uVisor API documentation](API.md)
nexpaq 1:55a6170b404f 328 * [Debugging uVisor on mbed OS](DEBUGGING.md)
nexpaq 1:55a6170b404f 329
nexpaq 1:55a6170b404f 330 If you found any bug or inconsistency in this guide, please [raise an issue](https://github.com/ARMmbed/uvisor/issues/new).
nexpaq 1:55a6170b404f 331
nexpaq 1:55a6170b404f 332 ## Appendix
nexpaq 1:55a6170b404f 333 [Go to top](#overview)
nexpaq 1:55a6170b404f 334
nexpaq 1:55a6170b404f 335 This section contains additional information that you might find useful when setting up a secure box.
nexpaq 1:55a6170b404f 336
nexpaq 1:55a6170b404f 337 ### The NVIC APIs
nexpaq 1:55a6170b404f 338
nexpaq 1:55a6170b404f 339 The ARM CMSIS header files provide APIs to configure, enable and disable IRQs in the NVIC module. These APIs are all prefixed with `NVIC_` and can be found in the `core_cm*.h` files in your CMSIS module.
nexpaq 1:55a6170b404f 340
nexpaq 1:55a6170b404f 341 In addition, the CMSIS header also provide APIs to set and get an interrupt vector at runtime. This requires the interrupt vector table, which is usually located in flash, to be relocated to SRAM.
nexpaq 1:55a6170b404f 342
nexpaq 1:55a6170b404f 343 When the uVisor is enabled, all NVIC APIs are re-routed to the corresponding uVisor vIRQ APIs, which virtualize the interrupt module. The uVisor interrupt model has the following features:
nexpaq 1:55a6170b404f 344
nexpaq 1:55a6170b404f 345 * The uVisor owns the interrupt vector table.
nexpaq 1:55a6170b404f 346 * All ISRs are relocated to SRAM.
nexpaq 1:55a6170b404f 347 * Code in a box can only change the state of an IRQ (enable it, change its priority, etc.) if the box registered that IRQ with uVisor at runtime, using the `NVIC_SetVector` API.
nexpaq 1:55a6170b404f 348 * An IRQ that belongs to a box can only be modified when that box context is active.
nexpaq 1:55a6170b404f 349
nexpaq 1:55a6170b404f 350 Although this behaviour is different from the original NVIC one, it is backwards compatible. This means that legacy code (like a device HAL) will still work after uVisor is enabled. The general use case is the following:
nexpaq 1:55a6170b404f 351
nexpaq 1:55a6170b404f 352 ```C
nexpaq 1:55a6170b404f 353 #define MY_IRQ 42
nexpaq 1:55a6170b404f 354
nexpaq 1:55a6170b404f 355 /* Set the ISR for MY_IRQ at runtime.
nexpaq 1:55a6170b404f 356 * Without uVisor: Relocate the interrupt vector table to SRAM and set my_isr as
nexpaq 1:55a6170b404f 357 the ISR for MY_IRQ.
nexpaq 1:55a6170b404f 358 * With uVisor: Register MY_IRQ for the current box with my_isr as ISR. */
nexpaq 1:55a6170b404f 359 NVIC_SetVector(MY_IRQ, &my_isr);
nexpaq 1:55a6170b404f 360
nexpaq 1:55a6170b404f 361 /* Change the IRQ state. */
nexpaq 1:55a6170b404f 362 NVIC_SetPriority(MY_IRQ, 3);
nexpaq 1:55a6170b404f 363 NVIC_EnableIRQ(MY_IRQ);
nexpaq 1:55a6170b404f 364 ```
nexpaq 1:55a6170b404f 365
nexpaq 1:55a6170b404f 366 > **Note**: In this model a call to `NVIC_SetVector` must always happen before an IRQ state is changed. In platforms that don't relocate the interrupt vector table such a call might be originally absent and must be added to work with uVisor.
nexpaq 1:55a6170b404f 367
nexpaq 1:55a6170b404f 368 For more information on the uVisor APIs, checkout the [uVisor API documentation](API.md) document.
nexpaq 1:55a6170b404f 369
nexpaq 1:55a6170b404f 370 ### The *main box* ACLs
nexpaq 1:55a6170b404f 371
nexpaq 1:55a6170b404f 372 The code samples that we provide in this guide give you a ready-made list of ACLs for the main box. The list includes peripherals that we already know will be necessary to make the example app work, and it is specific to the NXP FRDM-K64F target.
nexpaq 1:55a6170b404f 373
nexpaq 1:55a6170b404f 374 This section shows how to discover the needed ACLs for the main box. You might need to follow these instructions in case you want to generate the ACLs list for a different target or a different app.
nexpaq 1:55a6170b404f 375
nexpaq 1:55a6170b404f 376 At the moment the uVisor does not provide a way to detect and list all the faulting ACLs for a given platform automatically. This is a planned feature that will be released in the future.
nexpaq 1:55a6170b404f 377
nexpaq 1:55a6170b404f 378 In order to generate the list of ACLs, use the code provided in the [Enable uVisor](#enable-uvisor) section. In this case, though, start with an empty ACLs list:
nexpaq 1:55a6170b404f 379
nexpaq 1:55a6170b404f 380 ```C
nexpaq 1:55a6170b404f 381 static const UvisorBoxAclItem g_main_box_acls[] = {
nexpaq 1:55a6170b404f 382 }
nexpaq 1:55a6170b404f 383 ```
nexpaq 1:55a6170b404f 384
nexpaq 1:55a6170b404f 385 You now need to compile your application using uVisor in debug mode. This operation requires some more advanced steps, which are described in detail in the [Debugging uVisor on mbed OS](DEBUGGING.md) document. The main idea is that you compile the application in debug mode:
nexpaq 1:55a6170b404f 386
nexpaq 1:55a6170b404f 387 ```bash
nexpaq 1:55a6170b404f 388 $ mbed compile -m K64F -t GCC_ARM -o "debug-info"
nexpaq 1:55a6170b404f 389 ```
nexpaq 1:55a6170b404f 390
nexpaq 1:55a6170b404f 391 and then use a GDB-compatible interface to flash the device, enable semihosting, and access the uVisor debug messages. Please read the [Debugging uVisor on mbed OS](DEBUGGING.md) document for the detailed instructions.
nexpaq 1:55a6170b404f 392
nexpaq 1:55a6170b404f 393 Once the uVisor debug messages are enabled, you will see you application fail. The failure is due to the first missing ACL being hit by the main box code. The message will look like:
nexpaq 1:55a6170b404f 394
nexpaq 1:55a6170b404f 395 ```
nexpaq 1:55a6170b404f 396 ***********************************************************
nexpaq 1:55a6170b404f 397 BUS FAULT
nexpaq 1:55a6170b404f 398 ***********************************************************
nexpaq 1:55a6170b404f 399
nexpaq 1:55a6170b404f 400 ...
nexpaq 1:55a6170b404f 401
nexpaq 1:55a6170b404f 402 * MEMORY MAP
nexpaq 1:55a6170b404f 403 Address: 0x4004800C
nexpaq 1:55a6170b404f 404 Region/Peripheral: SIM
nexpaq 1:55a6170b404f 405 Base address: 0x40047000
nexpaq 1:55a6170b404f 406 End address: 0x40048060
nexpaq 1:55a6170b404f 407
nexpaq 1:55a6170b404f 408 ...
nexpaq 1:55a6170b404f 409 ```
nexpaq 1:55a6170b404f 410
nexpaq 1:55a6170b404f 411 Now that you know which peripheral is causing the fault (the `SIM` peripheral, in this example), you can add its entry to the ACLs list:
nexpaq 1:55a6170b404f 412
nexpaq 1:55a6170b404f 413
nexpaq 1:55a6170b404f 414 ```C
nexpaq 1:55a6170b404f 415 static const UvisorBoxAclItem g_main_box_acls[] = {
nexpaq 1:55a6170b404f 416 {SIM, sizeof(*SIM), UVISOR_TACLDEF_PERIPH},
nexpaq 1:55a6170b404f 417 };
nexpaq 1:55a6170b404f 418 ```
nexpaq 1:55a6170b404f 419
nexpaq 1:55a6170b404f 420 > **Note**: If the fault debug screen does not show the name of the peripheral, you need to look it up in the target device reference manual.
nexpaq 1:55a6170b404f 421
nexpaq 1:55a6170b404f 422 For readability, do not use the hard-coded addresses of your peripherals, but rather use the symbols provided by the target CMSIS module.
nexpaq 1:55a6170b404f 423
nexpaq 1:55a6170b404f 424 Repeat the process multiple times until all ACLs have been added to the list. When no other ACL is needed any more, the system will run without hitting a uVisor fault.