Linux Audio

Check our new training course

Loading...
/*
 * Copyright (c) 2013-2014 Wind River Systems, Inc.
 *
 * 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
 * @brief ARM CORTEX-M3 System Control Block interface
 *
 *
 * Most of the SCB interface consists of simple bit-flipping methods, and is
 * implemented as inline functions in scb.h. This module thus contains only data
 * definitions and more complex routines, if needed.
 */

#include <nanokernel.h>
#include <arch/cpu.h>
#include <misc/util.h>

#define SCB_AIRCR_VECTKEY_EN_W 0x05FA

#if defined(CONFIG_SOC_TI_LM3S6965_QEMU)
/*
 * QEMU is missing the support for rebooting through the SYSRESETREQ mechanism.
 * Just jump back to __reset() of the image in flash, which address can
 * _always_ be found in the vector table reset slot located at address 0x4.
 */

static void software_reboot(void)
{
	extern void _do_software_reboot(void);
	extern void _force_exit_one_nested_irq(void);
	/*
	 * force enable interrupts locked via PRIMASK if somehow disabled: the
	 * boot code does not enable them
	 */
	__asm__ volatile("cpsie i" :::);

	if (_ScbIsInThreadMode()) {
		_do_software_reboot();
	} else {
		__asm__ volatile(
			"ldr r0,  =_force_exit_one_nested_irq\n\t"
			"bx r0\n\t"
			:::);
	}
}
#define DO_REBOOT() software_reboot()
#else
static void reboot_through_sysresetreq(void)
{
	union __aircr reg;

	reg.val = __scs.scb.aircr.val;
	reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W;
	reg.bit.sysresetreq = 1;
	__scs.scb.aircr.val = reg.val;

	/* the reboot is not immediate, so wait here until it takes effect */
	for (;;) {
		;
	}
}
#define DO_REBOOT() reboot_through_sysresetreq()
#endif

/**
 *
 * @brief Reset the system
 *
 * This routine resets the processor.
 *
 * @return N/A
 */

void sys_arch_reboot(int type)
{
	ARG_UNUSED(type);
	DO_REBOOT();
}

/**
 *
 * @brief Set the number of priority groups based on the number of exception
 * priorities desired
 *
 * Exception priorities can be divided in priority groups, inside which there is
 * no preemption. The priorities inside a group are only used to decide which
 * exception will run when more than one is ready to be handled.
 *
 * The number of priorities has to be a power of two, from 1 to 128.
 *
 * @param n the number of priorities
 *
 * @return N/A
 */
void _ScbNumPriGroupSet(unsigned int n)
{
	unsigned int set;
	union __aircr reg;

	__ASSERT(is_power_of_two(n) && (n <= 128),
		 "invalid number of priorities");

	set = find_lsb_set(n);

	reg.val = __scs.scb.aircr.val;

	/* num pri    bit set   prigroup
	 * ---------------------------------
	 *      1        1          7
	 *      2        2          6
	 *      4        3          5
	 *      8        4          4
	 *     16        5          3
	 *     32        6          2
	 *     64        7          1
	 *    128        8          0
	 */

	reg.bit.prigroup = 8 - set;
	reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W;

	__scs.scb.aircr.val = reg.val;
}