/** @brief Provide mechanisms to specify which stack to use and for the processor to operate in Unprivileged mode and access Privileged mode.
 *
 * @copyright 2020 Remsdaq Ltd.
 * @file c4_privilege_modes.h
 *
 *  The iMXRT1062 processor has two processor modes and two privilege levels. There are
 *  two stacks available for use depending on the mode.
 *
 *   From the ARM® Cortex®- M7 Devices Generic User Guide(DUI046B, 2015)
 *
 * <b>2.1.1 Processor mode and privilege levels for software execution</b>
 *
 * The processor \em modes are:
 *
 * <b>Thread mode</b> Used to execute application software. The processor enters Thread mode
 * when it comes out of reset.
 *
 * <b>Handler mode</b> Used to handle exceptions. The processor returns to Thread mode when it
 * has finished all exception processing.
 *
 * The <em>privilege levels</em> for software execution are:
 *
 * \b Unprivileged The software:
 * \li Has limited access to the MSR and MRS instructions, and cannot use the
 * CPS instruction.
 * \li Cannot access the system timer, NVIC, or system control block.
 * \li Might have restricted access to memory or peripherals.
 *
 * <em>Unprivileged software</em> executes at the unprivileged level.
 *
 * \b Privileged The software can use all the instructions and has access to all resources.
 *
 * <em>Privileged software</em> executes at the privileged level.
 *
 * In Thread mode, the CONTROL register controls whether software execution is privileged or
 * unprivileged, see CONTROL register on page 2-9. In Handler mode, software execution is
 * always privileged.
 *
 * Only privileged software can write to the CONTROL register to change the privilege level for
 * software execution in Thread mode. Unprivileged software can use the \c SVC instruction to make
 * a <em>supervisor call</em> to transfer control to privileged software.
 *
 *
 * <b>2.1.2 Stacks</b>
 *
 * The processor uses a full descending stack. This means that the stack pointer holds the address
 * of the last stacked item in memory. When the processor pushes a new item onto the stack, it
 * decrements the stack pointer and then writes the item to the new memory location. The
 * processor implements two stacks, the <em>main stack</em> and the <em>process stack</em>, with a pointer for each
 * held in independent registers, see Stack Pointer on page 2-4.
 *
 * In Thread mode, the CONTROL register controls whether the processor uses the main stack or
 * the process stack, see CONTROL register on page 2-9. In Handler mode, the processor always
 * uses the main stack. The options for processor operations are:
 *
 * <table>
 * <caption id="Table 2-1"> Summary of processor mode, execution privilege level, and stack use options</caption>

 * <tr><th>Processor mode<th>Used to execute<th>Privilege level for software execution<th>Stack used
 * <tr><td>Thread<td>Applications<td>Privileged or unprivileged (a)<td>Main stack or process stack (a)
 * <tr><td>Handler<td>Exception handlers<td>Always privileged<td>Main stack
 * </table>
 * a. See CONTROL register on page 2-9.
 *
 * In an OS environment, the vendor recommends that threads running in Thread mode use the
 * process stack and the kernel and exception handlers use the main stack.
 *
 *  @date 8 Jul 2020
 *  @author Dan Smithers <dwhs@remsdaq.com>
 */



#ifndef C4_PRIVILEGE_MODES_H_
#define C4_PRIVILEGE_MODES_H_


/*******************************************************************************
 * Includes
 ******************************************************************************/

/*******************************************************************************
 * Defines
 ******************************************************************************/

/** @brief SVC operations.
 *
 * Ther first value (0) is reserved as it will be used by FreeRTOS.
 * The macro values are used to construct matching enumeration and string array
 * using the x-macro strategy.
 */
#define SVC_OPS    \
    CALLISTO_SVC(Reserved) \
    CALLISTO_SVC(PRINT) \
    CALLISTO_SVC(ADD) \
    CALLISTO_SVC(USER)

/** @brief Enumeration of operations performed by SVC.
 * The operation IDs need to fit into a uint8_t.
 */
typedef enum
{
#define CALLISTO_SVC(op) C4_SVC_##op,
    SVC_OPS
#undef CALLISTO_SVC
    C4_SVC_MAX_OPS
}C4_SVC_Op_t;

/** @brief Wrapper to call print as a privileged operation.
 */
#define C4_PRINT(...) printf(__VA_ARGS__)
//C4_executePrivileged(C4_SVC_PRINT, __VA_ARGS__)

/*******************************************************************************
 * Structures
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/** @brief Set the CONTROL register for Unprivileged level.
 */
void C4_enterUnprivileged();

/** @brief Execute operation in privileged mode.
 *
 * @param[in] op Enumerated ID of operation to be performed.
 */
void *C4_executePrivileged(C4_SVC_Op_t op, ...);

/* Handlers are defined in startup_mimxrt1062.c. */

/*******************************************************************************
 * Variables
 ******************************************************************************/

#endif /* C4_PRIVILEGE_MODES_H_ */
