Lee Kai Xuan / mbed-os

Fork of mbed-os by erkin yucel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers box_init.c Source File

box_init.c

00001 /*
00002  * Copyright (c) 2016, 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 #include "uvisor-lib/uvisor-lib.h"
00018 #include "api/inc/pool_queue_exports.h"
00019 #include "api/inc/rpc_exports.h"
00020 #include "api/inc/uvisor_semaphore.h"
00021 #include "mbed_interface.h"
00022 #include "cmsis_os.h"
00023 #include <stdint.h>
00024 #include <string.h>
00025 
00026 /* Register the OS with uVisor */
00027 extern void SVC_Handler(void);
00028 extern void PendSV_Handler(void);
00029 extern void SysTick_Handler(void);
00030 extern uint32_t rt_suspend(void);
00031 
00032 UVISOR_SET_PRIV_SYS_HOOKS(SVC_Handler, PendSV_Handler, SysTick_Handler, rt_suspend, __uvisor_semaphore_post);
00033 
00034 extern RtxBoxIndex * const __uvisor_ps;
00035 
00036 void __uvisor_initialize_rpc_queues(void)
00037 {
00038     UvisorBoxIndex * const index = &__uvisor_ps->index;
00039 
00040     uvisor_pool_slot_t i;
00041 
00042     uvisor_rpc_outgoing_message_queue_t * rpc_outgoing_msg_queue = index->rpc_outgoing_message_queue;
00043     uvisor_rpc_incoming_message_queue_t * rpc_incoming_msg_queue = index->rpc_incoming_message_queue;
00044     uvisor_rpc_fn_group_queue_t * rpc_fn_group_queue = index->rpc_fn_group_queue;
00045 
00046     /* Initialize the outgoing RPC message queue. */
00047     if (uvisor_pool_queue_init(&rpc_outgoing_msg_queue->queue,
00048                                &rpc_outgoing_msg_queue->pool,
00049                                rpc_outgoing_msg_queue->messages,
00050                                sizeof(*rpc_outgoing_msg_queue->messages),
00051                                UVISOR_RPC_OUTGOING_MESSAGE_SLOTS,
00052                                UVISOR_POOL_QUEUE_BLOCKING)) {
00053         uvisor_error(USER_NOT_ALLOWED);
00054     }
00055 
00056     /* Initialize all the result semaphores. */
00057     for (i = 0; i < UVISOR_RPC_OUTGOING_MESSAGE_SLOTS; i++) {
00058         UvisorSemaphore * semaphore = &rpc_outgoing_msg_queue->messages[i].semaphore;
00059         if (__uvisor_semaphore_init(semaphore, 1)) {
00060             uvisor_error(USER_NOT_ALLOWED);
00061         }
00062 
00063         /* Semaphores are created with their value initialized to count. We
00064          * want the semaphore to start at zero. Decrement the semaphore, so it
00065          * starts with a value of zero. This will allow the first pend to
00066          * block. */
00067         if (__uvisor_semaphore_pend(semaphore, 0)) {
00068             uvisor_error(USER_NOT_ALLOWED);
00069         }
00070     }
00071 
00072     /* Initialize the incoming RPC message queues. */
00073     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->todo_queue,
00074                                &rpc_incoming_msg_queue->pool,
00075                                rpc_incoming_msg_queue->messages,
00076                                sizeof(*rpc_incoming_msg_queue->messages),
00077                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS,
00078                                UVISOR_POOL_QUEUE_NON_BLOCKING)) {
00079         uvisor_error(USER_NOT_ALLOWED);
00080     }
00081     /* This is a double init of the pool. We need a function that just inits
00082      * the queue, not the pool, and init everybody separately. */
00083     if (uvisor_pool_queue_init(&rpc_incoming_msg_queue->done_queue,
00084                                &rpc_incoming_msg_queue->pool,
00085                                rpc_incoming_msg_queue->messages,
00086                                sizeof(*rpc_incoming_msg_queue->messages),
00087                                UVISOR_RPC_INCOMING_MESSAGE_SLOTS,
00088                                UVISOR_POOL_QUEUE_NON_BLOCKING)) {
00089         uvisor_error(USER_NOT_ALLOWED);
00090     }
00091 
00092     /* Initialize the function group pool. */
00093     if (uvisor_pool_queue_init(&rpc_fn_group_queue->queue,
00094                                &rpc_fn_group_queue->pool,
00095                                rpc_fn_group_queue->fn_groups,
00096                                sizeof(*rpc_fn_group_queue->fn_groups),
00097                                UVISOR_RPC_FN_GROUP_SLOTS,
00098                                UVISOR_POOL_QUEUE_BLOCKING)) {
00099         uvisor_error(USER_NOT_ALLOWED);
00100     }
00101 
00102     /* Initialize all the function group semaphores. */
00103     for (i = 0; i < UVISOR_RPC_FN_GROUP_SLOTS; i++) {
00104         UvisorSemaphore * semaphore = &rpc_fn_group_queue->fn_groups[i].semaphore;
00105         if (__uvisor_semaphore_init(semaphore, 1)) {
00106             uvisor_error(USER_NOT_ALLOWED);
00107         }
00108 
00109         /* Semaphores are created with their value initialized to count. We
00110          * want the semaphore to start at zero. Decrement the semaphore, so it
00111          * starts with a value of zero. This will allow the first pend to
00112          * block. */
00113         if (__uvisor_semaphore_pend(semaphore, 0)) {
00114             uvisor_error(USER_NOT_ALLOWED);
00115         }
00116     }
00117 }
00118 
00119 /* This function is called by uVisor in unprivileged mode. On this OS, we
00120  * create box main threads for the box. */
00121 void __uvisor_lib_box_init(void * lib_config)
00122 {
00123     osThreadId thread_id;
00124     osThreadDef_t * flash_thread_def = lib_config;
00125     osThreadDef_t thread_def;
00126 
00127     __uvisor_initialize_rpc_queues();
00128 
00129     /* Copy thread definition from flash to RAM. The thread definition is most
00130      * likely in flash, so we need to copy it to box-local RAM before we can
00131      * modify it. */
00132     memcpy(&thread_def, flash_thread_def, sizeof(thread_def));
00133 
00134     /* Note that the box main thread stack is separate from the box stack. This
00135      * is because the thread must be created to use a different stack than the
00136      * stack osCreateThread() is called from, as context information is saved
00137      * to the thread stack by the call to osCreateThread(). */
00138     /* Allocate memory for the main thread from the process heap (which is
00139      * private to the process). This memory is never freed, even if the box's
00140      * main thread exits. */
00141     thread_def.stack_pointer = malloc_p(thread_def.stacksize);
00142 
00143     if (thread_def.stack_pointer == NULL) {
00144         /* No process heap memory available */
00145         mbed_die();
00146     }
00147 
00148     thread_id = osThreadCreate(&thread_def, NULL);
00149 
00150     if (thread_id == NULL) {
00151         /* Failed to create thread */
00152         mbed_die();
00153     }
00154 }