增加所有文件

This commit is contained in:
2025-11-07 20:19:23 +08:00
parent b7376523b6
commit 846bd3bbda
8445 changed files with 3006231 additions and 5934 deletions

315
arch/armv7-r/arm_faults.c Normal file
View File

@@ -0,0 +1,315 @@
/*
* Copyright (c) 2008-2014 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <types.h>
#include <bits.h>
#include <param.h>
#include <ctype.h>
#include <debug.h>
#include <armv7-r/register.h>
#include <armv7-r/exceptions.h>
#include <armv7-r/arm.h>
#if CONFIG_OS_FREERTOS
#include <FreeRTOS.h>
#include <task.h>
#endif
static void dump_stack(const void *ptr, size_t len)
{
addr_t address = (addr_t)ptr;
size_t count;
for (count = 0 ; count < len; count += 16) {
union {
uint32_t buf[4];
uint8_t cbuf[16];
} u;
size_t s = ROUNDUP(MIN(len - count, 16), 4);
size_t i;
ssdk_printf(SSDK_EMERG, "0x%08x: ", address);
for (i = 0; i < s / 4; i++) {
u.buf[i] = ((const uint32_t *)address)[i];
ssdk_printf(SSDK_EMERG, "%08x ", u.buf[i]);
}
for (; i < 4; i++) {
ssdk_printf(SSDK_EMERG, " ");
}
ssdk_printf(SSDK_EMERG, "|");
for (i=0; i < 16; i++) {
unsigned char c = u.cbuf[i];
if (i < s && isprint(c)) {
ssdk_printf(SSDK_EMERG, "%c", c);
} else {
ssdk_printf(SSDK_EMERG, ".");
}
}
ssdk_printf(SSDK_EMERG, "|\r\n");
address += 16;
}
}
static void dump_mode_regs(uint32_t spsr, uint32_t svc_r13, uint32_t svc_r14)
{
struct arm_mode_regs regs;
arm_save_mode_regs(&regs);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_USR) ? '*' : ' ', "usr", regs.usr_r13, regs.usr_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", 'a', "svc", regs.svc_r13, regs.svc_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", svc_r13, svc_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
// dump the bottom of the current stack
addr_t stack;
switch (spsr & MODE_MASK) {
case MODE_FIQ:
stack = regs.fiq_r13;
break;
case MODE_IRQ:
stack = regs.irq_r13;
break;
case MODE_SVC:
stack = svc_r13;
break;
case MODE_UND:
stack = regs.und_r13;
break;
case MODE_SYS:
stack = regs.sys_r13;
break;
default:
stack = 0;
}
if (stack != 0) {
ssdk_printf(SSDK_EMERG, "bottom of stack at 0x%08x:\r\n", (unsigned int)stack);
dump_stack((void *)stack, 128);
}
}
static void dump_fault_frame(struct arm_fault_frame *frame)
{
#if CONFIG_OS_FREERTOS
TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
ssdk_printf(SSDK_EMERG, "current_thread %p, name %s\r\n",
current_thread, current_thread ? pcTaskGetName(current_thread) : "");
#endif
ssdk_printf(SSDK_EMERG, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\r\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
ssdk_printf(SSDK_EMERG, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\r\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
ssdk_printf(SSDK_EMERG, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\r\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
ssdk_printf(SSDK_EMERG, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\r\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
ssdk_printf(SSDK_EMERG, "spsr 0x%08x\r\n", frame->spsr);
dump_mode_regs(frame->spsr, (uintptr_t)(frame + 1), frame->lr);
}
static void dump_iframe(struct arm_iframe *frame)
{
ssdk_printf(SSDK_EMERG, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\r\n", frame->r0, frame->r1, frame->r2, frame->r3);
ssdk_printf(SSDK_EMERG, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\r\n", frame->r12, frame->usp, frame->ulr, frame->pc);
ssdk_printf(SSDK_EMERG, "spsr 0x%08x\r\n", frame->spsr);
dump_mode_regs(frame->spsr, (uintptr_t)(frame + 1), frame->lr);
}
static void exception_die(struct arm_fault_frame *frame, const char *msg)
{
ssdk_printf(SSDK_EMERG, "%s", msg);
dump_fault_frame(frame);
for (;;);
}
static void exception_die_iframe(struct arm_iframe *frame, const char *msg)
{
ssdk_printf(SSDK_EMERG, "%s", msg);
dump_iframe(frame);
for (;;);
}
void arm_undefined_handler(struct arm_iframe *frame)
{
/* look at the undefined instruction, figure out if it's something we can handle */
bool in_thumb = frame->spsr & (1<<5);
if (in_thumb) {
frame->pc -= 2;
} else {
frame->pc -= 4;
}
__UNUSED uint32_t opcode = *(uint32_t *)frame->pc;
ssdk_printf(SSDK_EMERG, "undefined opcode 0x%x\r\n", opcode);
#if CONFIG_ARCH_WITH_FPU
if (in_thumb) {
/* look for a 32bit thumb instruction */
if (opcode & 0x0000e800) {
/* swap the 16bit words */
opcode = (opcode >> 16) | (opcode << 16);
}
if (((opcode & 0xec000e00) == 0xec000a00) || // vfp
((opcode & 0xef000000) == 0xef000000) || // advanced simd data processing
((opcode & 0xff100000) == 0xf9000000)) { // VLD
ssdk_printf(SSDK_EMERG, "vfp/neon thumb instruction 0x%08x at 0x%x\r\n", opcode, frame->pc);
}
} else {
/* look for arm vfp/neon coprocessor instructions */
if (((opcode & 0x0c000e00) == 0x0c000a00) || // vfp
((opcode & 0xfe000000) == 0xf2000000) || // advanced simd data processing
((opcode & 0xff100000) == 0xf4000000)) { // VLD
ssdk_printf(SSDK_EMERG, "vfp/neon arm instruction 0x%08x at 0x%x\r\n", opcode, frame->pc);
}
}
#endif
exception_die_iframe(frame, "undefined abort, halting\r\n");
return;
}
void arm_data_abort_handler(struct arm_fault_frame *frame)
{
uint32_t fsr = arm_read_dfsr();
uint32_t far = arm_read_dfar();
uint32_t fault_status = (BIT(fsr, 10) ? (1<<4) : 0) | BITS(fsr, 3, 0);
ssdk_printf(SSDK_EMERG, "\r\n\ncpu data abort, ");
__UNUSED bool write = !!BIT(fsr, 11);
/* decode the fault status (from table B3-23) */
switch (fault_status) {
case 0x01: // alignment fault
ssdk_printf(SSDK_EMERG, "alignment fault on %s\r\n", write ? "write" : "read");
break;
case 0x05:
case 0x07: // translation fault
ssdk_printf(SSDK_EMERG, "translation fault on %s\r\n", write ? "write" : "read");
break;
case 0x03:
case 0x06: // access flag fault
ssdk_printf(SSDK_EMERG, "access flag fault on %s\r\n", write ? "write" : "read");
break;
case 0x09:
case 0x0B: // domain fault
ssdk_printf(SSDK_EMERG, "domain fault, domain %lu\r\n", BITS_SHIFT(fsr, 7, 4));
break;
case 0x0D:
case 0x0F: // permission fault
ssdk_printf(SSDK_EMERG, "permission fault on %s\r\n", write ? "write" : "read");
break;
case 0x02: // debug event
ssdk_printf(SSDK_EMERG, "debug event\r\n");
break;
case 0x08: // synchronous external abort
ssdk_printf(SSDK_EMERG, "synchronous external abort on %s\r\n", write ? "write" : "read");
break;
case 0x16: // asynchronous external abort
ssdk_printf(SSDK_EMERG, "asynchronous external abort on %s\r\n", write ? "write" : "read");
break;
case 0x10: // TLB conflict event
case 0x19: // synchronous parity error on memory access
case 0x04: // fault on instruction cache maintenance
case 0x0C: // synchronous external abort on translation table walk
case 0x0E: // "
case 0x1C: // synchronous parity error on translation table walk
case 0x1E: // "
case 0x18: // asynchronous parity error on memory access
default:
ssdk_printf(SSDK_EMERG, "unhandled fault\r\n");
break;
}
ssdk_printf(SSDK_EMERG, "DFAR 0x%x (fault address)\r\n", far);
ssdk_printf(SSDK_EMERG, "DFSR 0x%x (fault status register)\r\n", fsr);
exception_die(frame, "halting\r\n");
}
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
{
uint32_t fsr = arm_read_ifsr();
uint32_t far = arm_read_ifar();
uint32_t fault_status = (BIT(fsr, 10) ? (1<<4) : 0) | BITS(fsr, 3, 0);
ssdk_printf(SSDK_EMERG, "\r\n\ncpu prefetch abort, ");
/* decode the fault status (from table B3-23) */
switch (fault_status) {
case 0x01: // alignment fault
ssdk_printf(SSDK_EMERG, "alignment fault\r\n");
break;
case 0x05:
case 0x07: // translation fault
ssdk_printf(SSDK_EMERG, "translation fault\r\n");
break;
case 0x03:
case 0x06: // access flag fault
ssdk_printf(SSDK_EMERG, "access flag fault\r\n");
break;
case 0x09:
case 0x0B: // domain fault
ssdk_printf(SSDK_EMERG, "domain fault, domain %lu\r\n", BITS_SHIFT(fsr, 7, 4));
break;
case 0x0D:
case 0x0F: // permission fault
ssdk_printf(SSDK_EMERG, "permission fault\r\n");
break;
case 0x02: // debug event
ssdk_printf(SSDK_EMERG, "debug event\r\n");
break;
case 0x08: // synchronous external abort
ssdk_printf(SSDK_EMERG, "synchronous external abort\r\n");
break;
case 0x16: // asynchronous external abort
ssdk_printf(SSDK_EMERG, "asynchronous external abort\r\n");
break;
case 0x10: // TLB conflict event
case 0x19: // synchronous parity error on memory access
case 0x04: // fault on instruction cache maintenance
case 0x0C: // synchronous external abort on translation table walk
case 0x0E: // "
case 0x1C: // synchronous parity error on translation table walk
case 0x1E: // "
case 0x18: // asynchronous parity error on memory access
default:
ssdk_printf(SSDK_EMERG, "unhandled fault\r\n");
break;
}
ssdk_printf(SSDK_EMERG, "IFAR 0x%x (fault address)\r\n", far);
ssdk_printf(SSDK_EMERG, "IFSR 0x%x (fault status register)\r\n", fsr);
exception_die(frame, "halting\r\n");
}

54
arch/armv7-r/arm_fpu.c Normal file
View File

@@ -0,0 +1,54 @@
/*
* arm_fpu.c
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM fpu function.
*
* Revision History:
* -----------------
*/
#if CONFIG_ARCH_WITH_FPU
#include <armv7-r/register.h>
#include <armv7-r/fpu.h>
/* CPACR */
#define CPACR_CP10_SHIFT (20)
#define CPACR_CP10_MASK (3 << CPACR_CP10_SHIFT)
#define CPACR_CP11_SHIFT (22)
#define CPACR_CP11_MASK (3 << CPACR_CP11_SHIFT)
/* FPEXC */
#define FPEXC_EX (31)
#define FPEXC_EN (30)
/*
* fpu enable.
*/
void arm_fpu_enable(void)
{
uint32_t cpacr = arm_read_cpacr();
cpacr |= ((3 << CPACR_CP10_SHIFT) | (3 << CPACR_CP11_SHIFT));
arm_write_cpacr(cpacr);
uint32_t fpexc = arm_read_fpexc();
fpexc |= (1 << FPEXC_EN);
arm_write_fpexc(fpexc);
}
/*
* fpu disable.
*/
void arm_fpu_disable(void)
{
uint32_t fpexc = arm_read_fpexc();
fpexc &= ~(1 << FPEXC_EN);
arm_write_fpexc(fpexc);
}
#endif

101
arch/armv7-r/arm_irq.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* arm_irq.c
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM irq function.
*
* Revision History:
* -----------------
*/
#include <armv7-r/arm.h>
#include <armv7-r/register.h>
#include <bits.h>
#include <debug.h>
#include <types.h>
#include "irq.h"
/*
* is irq masked.
*
* @return masked or not.
*/
bool arch_irq_is_masked(void)
{
uint32_t cpsr = read_cpsr();
return (!!(cpsr & PSR_I_BIT));
}
/*
* is irq mode.
*
* @return irq mode or not.
*/
bool arch_in_irq_mode(void)
{
uint32_t cpsr;
uint8_t mode;
cpsr = read_cpsr();
mode = cpsr & MODE_MASK;
return ((mode != MODE_USR) && (mode != MODE_SYS));
}
/**
* @brief Enable vectored interrupt mode.
*/
void arch_vectored_irq_enable(bool en)
{
uint32_t sctlr;
sctlr = arm_read_sctlr();
if (en) {
sctlr |= 1U << 24;
} else {
sctlr &= ~(1U << 24);
}
arm_write_sctlr(sctlr);
}
/**
* @brief Whether core is in FIQ mode or not
*
* @return true FIQ mode
* @return false otherwise
*/
bool arch_in_fiq_mode(void)
{
uint32_t cpsr = read_cpsr();
return (cpsr & MODE_MASK) == MODE_FIQ;
}
/**
* @brief irq handler
*
* This function is used by irq interrupt when VE != 1.
*
*/
void arm_irq_handler(void)
{
#ifdef USE_STACK_COLORATION
if (!arch_check_exception_stack()) {
ssdk_printf(SSDK_ALERT, "exception stack overflow!\r\n");
return;
}
#endif
irq_dispatch();
}
/**
* @brief fiq handler
*
* This function is used by fiq interrupt.
*
*/
void arm_fiq_handler(void) { irq_dispatch(); }

248
arch/armv7-r/arm_mpu.c Normal file
View File

@@ -0,0 +1,248 @@
/*
* mpu.c
*
* Copyright (c) 2019 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R MPU driver.
*
* Revision History:
* -----------------
*/
#if CONFIG_ARCH_WITH_MPU
#include <armv7-r/arm.h>
#include <armv7-r/mpu.h>
#include <armv7-r/register.h>
#include <math.h>
#include <bits.h>
#include <debug.h>
/* RBAR bits [31:5] */
#define MPU_RBAR_MASK (0xffffffe0)
/* RACR bits */
#define MPU_RACR_B_SHIFT (0) /* Bufferable */
#define MPU_RACR_C_SHIFT (1) /* Cacheable */
#define MPU_RACR_S_SHIFT (2) /* Sharable. For normal memory only. */
#define MPU_RACR_TEX_SHIFT (3) /* Type extension */
#define MPU_RACR_AP_SHIFT (8) /* Access permission */
#define MPU_RACR_XN_SHIFT (12) /* Execution Never */
/* RACR Access permissions */
#define RACR_AP_NO_NO (0) /* Privileged NO, Unprivileged NO */
#define RACR_AP_RW_NO (1) /* Privileged RW, Unprivileged NO */
#define RACR_AP_RW_RO (2) /* Privileged RW, Unprivileged RO */
#define RACR_AP_RW_RW (3) /* Privileged RW, Unprivileged RW */
#define RACR_AP_RO_NO (5) /* Privileged RO, Unprivileged NO */
#define RACR_AP_RO_RO (6) /* Privileged RO, Unprivileged RO */
#define MPU_RACR_CONFIG(TEX, C, B, S, AP, XN) \
((B << MPU_RACR_B_SHIFT) | \
(C << MPU_RACR_C_SHIFT) | \
(S << MPU_RACR_S_SHIFT) | \
(TEX << MPU_RACR_TEX_SHIFT) | \
(AP << MPU_RACR_AP_SHIFT) | \
(XN << MPU_RACR_XN_SHIFT))
/* Region Size and Enable Register */
#define RSR_EN (1 << 0) /* Enable region */
#define RSR_SIZE_SHIFT (1) /* Region Size = log2(size) - 1 */
static const uint32_t g_racr_config[] = {
[MPU_REGION_STRONGORDERED] = MPU_RACR_CONFIG(
0, 0, 0, /* See "TEX[2:0], C and B encodings" */
0, /* S bit is not used for strong ordered. */
RACR_AP_RW_RW,
1 /* XN */
),
[MPU_REGION_DEVICE] = MPU_RACR_CONFIG(
0, 0, 1,
0, /* S bit is not used for device memory */
RACR_AP_RW_RW,
1 /* XN */
),
[MPU_REGION_NORMAL] = MPU_RACR_CONFIG(
0, 1, 1, /* cacheable, WB, no WA */
0, /* Not shared. R5 L1 cache does not cache shared
normal regions */
RACR_AP_RW_RW,
0 /* non XN */
),
[MPU_REGION_NORMAL_NONCACHEABLE] = MPU_RACR_CONFIG(
1, 0, 0, /* non-cacheable */
0,
RACR_AP_RW_RW,
0 /* non XN */
),
[MPU_REGION_NORMAL_RO] = MPU_RACR_CONFIG(
0, 1, 1, /* cacheable, WB, no WA */
0, /* Not shared. R5 L1 cache does not cache shared
normal regions */
RACR_AP_RO_RO,
0 /* XN */
),
[MPU_REGION_NO_ACCESS] = MPU_RACR_CONFIG(
0,
0,
0,
0,
RACR_AP_NO_NO,
0
),
};
uint32_t all_region_index = 0;
static int mpu_region_nr(void)
{
uint32_t val = arm_read_mpuir();
return (int)BITS_SHIFT(val, 15, 8); /* 0, 12 or 16 */
}
/*
* Clear MPU region.
*/
void mpu_clear_region(void)
{
int region_nr = mpu_region_nr();
for (int cnt = 0; cnt < region_nr; cnt++) {
arm_write_rgnr(cnt);
arm_write_rsr(0);
}
}
/*
* Add MPU region.
*
* @region Region index from 0 to mpu_region_nr - 1.
* @base Base address of the region. Must align to region size.
* @size Region size. Must be power of 2, from 32 bytes to 4GB.
* @type Region type.
*/
#if CONFIG_ARMV7R_MPU_CACHE_ALIGN_CHECK
struct region_info {
uint32_t base;
uint32_t end;
//mpu_region_type type;
};
struct region_info region_array[16] = {0};
int region_index = 0;
static void add_region(uint32_t base, uint32_t size)
{
ASSERT(region_index >= 0 && region_index < 16);
region_array[region_index].base = base;
region_array[region_index].end = base + size;
region_index++;
}
bool mpu_is_belong_uncache_region(uint32_t base, uint32_t size)
{
int i;
for (i = 0; i < region_index; i++) {
uint32_t end = base + size;
if (base >= region_array[i].base && end <= region_array[i].end) {
return true;
}
}
return false;
}
#endif
void mpu_add_region(int region, uint32_t base, uint64_t size,
mpu_region_type_e type)
{
ASSERT(region >= 0 && region < mpu_region_nr());
ASSERT((size & (size - 1)) == 0 &&
size >= 32ull &&
size <= 4ull * 1024 * 1024 * 1024);
ASSERT(base % size == 0);
ASSERT(type < MPU_REGION_MAX);
/* Calculate size field of RSR register.
* pow(2, sz + 1) = size
*/
uint32_t sz = (uint32_t)log2(size) - 1;
arm_write_rgnr(region);
arm_write_rbar(base & MPU_RBAR_MASK);
arm_write_racr(g_racr_config[type]);
/* TODO - support sub regions? */
arm_write_rsr((sz << RSR_SIZE_SHIFT) | RSR_EN);
#if CONFIG_ARMV7R_MPU_CACHE_ALIGN_CHECK
//add region in nocache list
if (type != MPU_REGION_NORMAL) {
add_region(base, size);
}
#endif
all_region_index++;
}
uint32_t mpu_region_index(void)
{
return all_region_index;
}
/*
* Enable or disable the MPU.
*
* MPU regions must have been configured before enabling the MPU.
*/
void mpu_enable(bool enable)
{
uint32_t val = arm_read_sctlr();
if (enable)
/* Enable MPU. The default background region is always
* enabled as well.
*/
{
val |= SCTLR_BR | SCTLR_M;
}
else {
val &= ~SCTLR_M;
}
arm_write_sctlr(val);
}
void mpu_region_set_type(uint32_t base, uint64_t size,
mpu_region_type_e type)
{
ASSERT((size & (size - 1)) == 0 &&
size >= 32ull &&
size <= 4ull * 1024 * 1024 * 1024);
ASSERT(base % size == 0);
ASSERT(type < MPU_REGION_MAX);
/* Calculate size field of RSR register.
* pow(2, sz + 1) = size
*/
uint32_t sz = (uint32_t)log2(size) - 1;
int region_nr = mpu_region_nr();
for (int cnt = 0; cnt < region_nr; cnt++) {
uint32_t rbar, rsr;
arm_write_rgnr(cnt);
rbar = arm_read_rbar();
rsr = arm_read_rsr();
if (((rbar & MPU_RBAR_MASK) == base)
&& (rsr >> RSR_SIZE_SHIFT) == sz) {
arm_write_rsr(rsr & ~RSR_EN);
arm_write_racr(g_racr_config[type]);
arm_write_rsr(rsr);
}
}
}
#endif

109
arch/armv7-r/arm_tcm.c Normal file
View File

@@ -0,0 +1,109 @@
/*
* arm_tcm.c
*
* Copyright (c) 2019 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R TCM driver.
*
* Revision History:
* -----------------
*/
#if CONFIG_ARM_WITH_TCM
#include <types.h>
#include <compiler.h>
#include <bits.h>
#include <param.h>
#include <armv7-r/tcm.h>
#include <armv7-r/register.h>
/**
* @brief Clear the TCM.
*/
extern void tcm_clear_64bit(uint32_t base, size_t size);
/**
* @brief Get TCMA size in bytes.
*/
static size_t tcma_get_size(void)
{
uint32_t atcm_size = BITS_SHIFT(arm_read_atcmrgn(), 6, 2);
return (1 << (atcm_size + 9));
}
/**
* @brief Get TCMB size in bytes.
*/
static size_t tcmb_get_size(void)
{
uint32_t btcm_size = BITS_SHIFT(arm_read_btcmrgn(), 6, 2);
return (1 << (btcm_size + 9));
}
/**
* @brief Enable the TCMA.
*/
void tcma_enable(uint32_t atcm_base, bool enable_ecc)
{
size_t atcm_size;
uint32_t actlr = arm_read_actlr();
/* Disable ECC by default */
actlr &= ~ATCMPCEN;
arm_write_actlr(actlr);
/* Get TCM size. */
atcm_size = tcma_get_size();
/* Update TCM base address. */
if (atcm_size != 0) {
arm_write_atcmrgn(atcm_base | 1);
}
if (enable_ecc) {
/* Write to the TCM in 64-bit aligned quantities to initialize
* ECC codes.
*/
tcm_clear_64bit(atcm_base, atcm_size);
/* Enable ECC. */
actlr |= ATCMPCEN;
arm_write_actlr(actlr);
}
}
/**
* @brief Enable the TCMB.
*/
void tcmb_enable(uint32_t btcm_base, bool enable_ecc)
{
size_t btcm_size;
uint32_t actlr = arm_read_actlr();
/* Disable ECC by default */
actlr &= ~(B0TCMPCEN | B1TCMPCEN);
arm_write_actlr(actlr);
/* Get TCM size. */
btcm_size = tcmb_get_size();
/* Update TCM base address. */
if (btcm_size != 0) {
arm_write_btcmrgn(btcm_base | 1);
}
if (enable_ecc) {
/* Write to the TCM in 64-bit aligned quantities to initialize
* ECC codes.
*/
tcm_clear_64bit(btcm_base, btcm_size);
/* Enable ECC. */
actlr |= B0TCMPCEN | B1TCMPCEN;
arm_write_actlr(actlr);
}
}
#endif

View File

@@ -0,0 +1,57 @@
/*
* arm_atomic.s
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM atomic function.
*
* Revision History:
* -----------------
*/
#include <config.h>
#include <compiler.h>
.text
FUNCTION(arch_atomic_swap)
.Lloop_atomic_swap:
ldrex r12, [r0]
strex r2, r1, [r0]
cmp r2, #0
bne .Lloop_atomic_swap
mov r0, r12
bx lr
.arm
FUNCTION(arch_atomic_add)
.Lloop_atomic_add:
ldrex r12, [r0]
add r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_add
mov r0, r12
bx lr
FUNCTION(arch_atomic_and)
.Lloop_atomic_and:
ldrex r12, [r0]
and r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_and
mov r0, r12
bx lr
FUNCTION(arch_atomic_or)
.Lloop_atomic_or:
ldrex r12, [r0]
orr r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_or
mov r0, r12
bx lr

View File

@@ -0,0 +1,317 @@
/*
* Copyright (c) 2008-2012 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/cache.h>
#if CONFIG_ARCH_WITH_CACHE
.text
.arm
/* void arch_disable_cache(uint flags) */
FUNCTION(arch_disable_cache)
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r8, cpsr // save the old interrupt state
cpsid iaf // interrupts disabled
.Ldcache_disable:
tst r7, #DCACHE
beq .Licache_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already disabled?
beq .Ldcache_already_disabled
bic r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // disable dcache
// flush and invalidate the dcache
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl flush_invalidate_cache_v7
b .Ldcache_disable_L2
.Ldcache_already_disabled:
// make sure all of the caches are invalidated
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
.Ldcache_disable_L2:
#if CONFIG_ARCH_L2CACHE
// disable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
bic r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
#endif
.Licache_disable:
tst r7, #ICACHE
beq .Ldone_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
bic r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // disable icache
.Ldone_disable:
// make sure the icache is always invalidated
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
msr cpsr, r8
ldmfd sp!, {r4-r11, pc}
/* void arch_enable_cache(uint flags) */
FUNCTION(arch_enable_cache)
stmfd sp!, {r4-r12, lr}
mov r7, r0 // save flags
mrs r8, cpsr // save the old interrupt state
cpsid iaf // interrupts disabled
.Ldcache_enable:
tst r7, #DCACHE
beq .Licache_enable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
// invalidate L1 and L2
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
#if CONFIG_ARCH_L2CACHE
// enable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
orr r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
#endif
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // enable dcache
.Licache_enable:
tst r7, #ICACHE
beq .Ldone_enable
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // enable icache
.Ldone_enable:
isb
msr cpsr, r8
ldmfd sp!, {r4-r12, pc}
// flush & invalidate cache routine, trashes r0-r6, r9-r11
flush_invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
dmb
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished
MOV R10, #0
.Loop1:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
isb // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3
SUBS R6, R6, #1 // decrement the index
BGE .Loop2
.Lskip:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1
.Lfinished:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
dsb
isb
bx lr
// invalidate cache routine, trashes r0-r6, r9-r11
invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
dmb
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished_invalidate
MOV R10, #0
.Loop1_invalidate:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip_invalidate // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
isb // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2_invalidate:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3_invalidate:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3_invalidate
SUBS R6, R6, #1 // decrement the index
BGE .Loop2_invalidate
.Lskip_invalidate:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1_invalidate
.Lfinished_invalidate:
dsb
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
isb
bx lr
/* void arch_flush_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_cache_range)
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
0:
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
add r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo 0b
dsb
#endif
bx lr
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_invalidate_cache_range)
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
0:
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate dcache to PoC by MVA
add r0, r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo 0b
dsb
#endif
bx lr
/* void arch_clean_invalidate_dcache_all(void); */
FUNCTION(arch_clean_invalidate_dcache_all)
#if CONFIG_ARM_WITH_CP15
mrc p15, 1, r0, c0, c0, 0 /* Read the Cache Size Identification Register */
ldr r3, =0x7fff /* Isolate the NumSets field (bits 13-27) */
and r0, r3, r0, lsr #13 /* r0=NumSets (number of sets - 1) */
mov r1, #0 /* r1 = way loop counter */
way_loop:
mov r3, #0 /* r3 = set loop counter */
set_loop:
mov r2, r1, lsl #30 /* r2 = way loop counter << 30 */
orr r2, r3, lsl #5 /* r2 = set/way cache operation format */
mcr p15, 0, r2, c7, c14, 2 /* Data Cache Clean Invalidate by Set/Way */
add r3, r3, #1 /* Increment set counter */
cmp r0, r3 /* Last set? */
bge set_loop /* Keep looping if not */
add r1, r1, #1 /* Increment the way counter */
cmp r1, #4 /* Last way? (four ways assumed) */
bne way_loop /* Keep looping if not */
dsb
#endif
bx lr
/* void arch_invalidate_cache_range(addr_t start, size_t len); */
FUNCTION(arch_invalidate_cache_range)
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
0:
mcr p15, 0, r0, c7, c6, 1 // invalidate dcache to PoC by MVA
add r0, r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo 0b
dsb
#endif
bx lr
/* void arch_sync_cache_range(addr_t start, size_t len); */
FUNCTION(arch_sync_cache_range)
push { r14 }
bl arch_clean_cache_range
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
pop { pc }
#endif

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 2008-2015 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/cache.h>
/* macros to align and unalign the stack on 8 byte boundary for ABI compliance */
.macro stack_align, tempreg
/* make sure the stack is aligned */
mov \tempreg, sp
tst sp, #4
subeq sp, #4
push { \tempreg }
/* tempreg holds the original stack */
.endm
.macro stack_restore, tempreg
/* restore the potentially unaligned stack */
pop { \tempreg }
mov sp, \tempreg
.endm
/* save and disable the vfp unit */
.macro vfp_save, temp1
/* save old fpexc */
vmrs \temp1, fpexc
push { \temp1 }
/* hard disable the vfp unit */
bic \temp1, #(1<<30)
vmsr fpexc, \temp1
.endm
/* restore the vfp enable/disable state */
.macro vfp_restore, temp1
/* restore fpexc */
pop { \temp1 }
vmsr fpexc, \temp1
.endm
/* Save callee trashed registers.
* At exit r0 contains a pointer to the register frame.
*/
.macro save
/* save spsr and r14 onto the svc stack */
srsdb #0x13!
/* switch to svc mode, interrupts disabled */
cpsid i,#0x13
/* save callee trashed regs and lr */
push { r0-r4, r12, lr }
/* save user space sp/lr */
sub sp, #8
stmia sp, { r13, r14 }^
#if CONFIG_ARCH_WITH_FPU
/* save and disable the vfp unit */
vfp_save r0
#endif
/* make sure the stack is 8 byte aligned */
stack_align r0
/* r0 now holds the pointer to the original iframe (before alignment) */
.endm
.macro save_offset, offset
sub lr, \offset
save
.endm
.macro restore
/* undo the stack alignment we did before */
stack_restore r0
#if CONFIG_ARCH_WITH_FPU
/* restore the old state of the vfp unit */
vfp_restore r0
#endif
/* restore user space sp/lr */
ldmia sp, { r13, r14 }^
add sp, #8
pop { r0-r4, r12, lr }
/* return to whence we came from */
rfeia sp!
.endm
/* Save all registers.
* At exit r0 contains a pointer to the register frame.
*/
.macro saveall
/* save spsr and r14 onto the svc stack */
srsdb #0x13!
/* switch to svc mode, interrupts disabled */
cpsid i,#0x13
/* save all regs */
push { r0-r12, lr }
/* save user space sp/lr */
sub sp, #8
stmia sp, { r13, r14 }^
#if CONFIG_ARCH_WITH_FPU
/* save and disable the vfp unit */
vfp_save r0
#endif
/* make sure the stack is 8 byte aligned */
stack_align r0
/* r0 now holds the pointer to the original iframe (before alignment) */
.endm
.macro saveall_offset, offset
sub lr, \offset
saveall
.endm
.macro restoreall
/* undo the stack alignment we did before */
stack_restore r0
#if CONFIG_ARCH_WITH_FPU
/* restore the old state of the vfp unit */
vfp_restore r0
#endif
/* restore user space sp/lr */
ldmia sp, { r13, r14 }^
add sp, #8
pop { r0-r12, r14 }
/* return to whence we came from */
rfeia sp!
.endm
.arm
FUNCTION(arm_save_mode_regs)
mrs r1, cpsr
stmia r0, { r13, r14 }^ /* usr */
add r0, #8
cps #0x11 /* fiq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x12 /* irq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x13 /* svc */
str r13, [r0], #4
str r14, [r0], #4
cps #0x17 /* abt */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1b /* und */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1f /* sys */
str r13, [r0], #4
str r14, [r0], #4
msr cpsr_c, r1
bx lr
FUNCTION(Arm_Undefined_Handler)
save
/* r0 now holds pointer to iframe */
bl arm_undefined_handler
restore
FUNCTION(Arm_Prefetch_Handler)
saveall_offset #4
/* r0 now holds pointer to iframe */
bl arm_prefetch_abort_handler
restoreall
FUNCTION(Arm_Abort_Handler)
saveall_offset #8
/* r0 now holds pointer to iframe */
bl arm_data_abort_handler
restoreall
FUNCTION(Arm_SWI_Handler)
/* not support */
ldr r0,=Arm_SWI_Handler
bx r0
FUNCTION(Arm_IRQ_Handler)
sub lr, lr, #4
srsdb #0x13!
cpsid i,#0x13
push {r0-r4, r12, lr}
sub sp, #8
stmia sp, {r13, r14}^
mov r2, sp
tst sp, #4
subeq sp, #4
push {r2}
push {r0, lr}
bl arm_irq_handler
pop {r0, lr}
pop {r2}
mov sp, r2
ldmia sp, {r13, r14}^
add sp, #8
pop {r0-r4, r12, lr}
rfeia sp!
FUNCTION(Arm_FIQ_Handler)
push {r0-r3, r12, lr}
blx arm_fiq_handler
pop {r0-r3, r12, lr}
subs pc, lr, #4
FUNCTION(arm_reserved)
b .

View File

@@ -0,0 +1,44 @@
/*
* arm_fullcontextrestore.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM full context restore.
*
* Revision History:
* -----------------
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/svcall.h>
/****************************************************************************
* Public Functions
****************************************************************************/
.text
/****************************************************************************
* Name: arm_fullcontextrestore
****************************************************************************/
.globl arm_fullcontextrestore
.type arm_fullcontextrestore, function
arm_fullcontextrestore:
cps #0x1F /* Enter sys mode */
/* Perform the System call with R0=1 and R1=regs */
mov r1, r0 /* R1: regs */
mov r0, #SYS_restore_context /* R0: restore context */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
/* This call should not return */
bx lr /* Unnecessary ... will not return */
.size arm_fullcontextrestore, .-arm_fullcontextrestore
.end

View File

@@ -0,0 +1,41 @@
/*
* arm_saveusercontext.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM save user context.
*
* Revision History:
* -----------------
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/svcall.h>
/****************************************************************************
* Public Functions
****************************************************************************/
.text
/****************************************************************************
* Name: arm_saveusercontext
****************************************************************************/
.globl arm_saveusercontext
.type arm_saveusercontext, function
arm_saveusercontext:
/* Perform the System call with R0=0 and R1=regs */
mov r1, r0 /* R1: regs */
mov r0, #SYS_save_context /* R0: save context (also return value) */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
bx lr
.size arm_saveusercontext, .-arm_saveusercontext
.end

View File

@@ -0,0 +1,42 @@
/*
* arm_switchcontext.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM switch context.
*
* Revision History:
* -----------------
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/svcall.h>
/****************************************************************************
* Public Functions
****************************************************************************/
.text
/****************************************************************************
* Name: arm_switchcontext
****************************************************************************/
.globl arm_switchcontext
.type arm_switchcontext, function
arm_switchcontext:
/* Perform the System call with R0=2 */
mov r0, #SYS_switch_context /* R0: context switch */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
/* We will get here only after the rerturn from the context switch */
bx lr
.size arm_switchcontext, .-arm_switchcontext
.end

View File

@@ -0,0 +1,122 @@
/*
* arm_tcm.S
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R TCM driver.
*
* Revision History:
* -----------------
*/
#include <config.h>
#include <compiler.h>
#include <armv7-r/tcm.h>
#if CONFIG_ARM_WITH_TCM
.text
.macro tcm_enable, idx, addr_reg, temp_reg
orr \temp_reg, \addr_reg, #1
mcr p15, 0, \temp_reg, c9, c1, \idx
.endm
.macro tcm_enable_ecc, temp_reg, val
mrc p15, 0, \temp_reg, c1, c0, 1
orr \temp_reg, \temp_reg, #(\val)
mcr p15, 0, \temp_reg, c1, c0, 1
.endm
.macro tcm_disable_ecc, temp_reg, val
mrc p15, 0, \temp_reg, c1, c0, 1
bic \temp_reg, \temp_reg, #(\val)
mcr p15, 0, \temp_reg, c1, c0, 1
.endm
.macro tcm_get_size, idx, size_reg, temp_reg
mrc p15, 0, \size_reg, c9, c1, \idx
ubfx \size_reg, \size_reg, #2, #5
adds \size_reg, #9
movs \temp_reg, #1
lsls \size_reg, \temp_reg, \size_reg
.endm
.macro tcm_clear, addr_reg, size_reg, temp_reg1, temp_reg2
mov \temp_reg1, #0
mov \temp_reg2, #0
add \size_reg, \addr_reg, \size_reg
.Ltcm_loop\@:
cmp \addr_reg, \size_reg
bhs .Ltcm_loop_end\@
stmia \addr_reg!, {\temp_reg1-\temp_reg2}
b .Ltcm_loop\@
.Ltcm_loop_end\@:
.endm
.arm
/* This function not store registers,
* only used before stack setup.
*/
FUNCTION(tcma_enable_early)
/* disable ecc */
tcm_disable_ecc r4, ATCMPCEN
/* read tcma size, r2 save size */
tcm_get_size 1, r2, r4
/* enable tcma, r0 save addr */
tcm_enable 1, r0, r4
/* check enable ecc */
cmp r1, #1
bne .Lout
/* clear tcma */
tcm_clear r0, r2, r6, r7
/* enalbe ecc */
tcm_enable_ecc r4, ATCMPCEN
b .Lout
/* This function not store registers,
* only used before stack setup.
*/
FUNCTION(tcmb_enable_early)
/* disable ecc */
tcm_disable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
/* read tcma size, r2 save size */
tcm_get_size 0, r2, r4
/* enable tcma, r0 save addr */
tcm_enable 0, r0, r4
/* check enable ecc */
cmp r1, #1
bne .Lout
/* clear tcma */
tcm_clear r0, r2, r6, r7
/* enalbe ecc */
tcm_enable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
b .Lout
/* Clear the TCM, each store must be 64 bits aligned. */
FUNCTION(tcm_clear_64bit)
push {r6, r7}
tcm_clear r0, r1, r6, r7
pop {r6, r7}
.Lout:
bx lr
#endif

View File

@@ -0,0 +1,133 @@
/*
* context_saverestore.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
.macro portMPU_RegisterSave
MOV r0, #0
mpu_save_loop:
MCR p15, 0, r0, c6, c2, 0
MRC p15, 0, r2, c6, c1, 0
STR r2, [r1], #4
MRC p15, 0, r2, c6, c1, 4
STR r2, [r1], #4
MRC p15, 0, r2, c6, c1, 2
STR r2, [r1], #4
ADD r0, r0, #1
CMP r0, #16
BNE mpu_save_loop
MRC p15, 0, r2, c1, c0, 0
STR r2, [r1], #4
.endm
; /**********************************************************************/
.macro portMPU_RegisterRestore
MRC p15, 0, r2, c1, c0, 0
LDR r0, =(SCTLR_BR | SCTLR_M)
BIC r2, r2, r0
MCR p15, 0, r2, c1, c0, 0
MOV r0, #0
mpu_restore_loop:
MCR p15, 0, r0, c6, c2, 0
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 0
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 4
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 2
ADD r0, r0, #1
CMP r0, #16
BNE mpu_restore_loop
MRC p15, 0, r0, c1, c0, 0
LDR r2, =(SCTLR_BR | SCTLR_M)
ORR r0, r0, r2
LDR r2, [r1], #4
TST r2, #SCTLR_M
MCRNE p15, 0, r0, c1, c0, 0
.endm
; /**********************************************************************/
.macro portCPU_RegisterSave
PUSH {r0-r3, r12}
STMIA r1, {r0-r12}
STR lr, [r1, #(4*REG_R15)]
MRS r2, SPSR
STR r2, [r1, #(4*REG_CPSR)]
#if CONFIG_ARCH_WITH_FPU
ADD r3, r1, #(4*REG_S0)
VSTMIA r3!, {s0-s31}
VMRS r2, fpscr
STR r2, [r3], #4
#endif
CPS #SYS_MODE
ADD r3, r1, #(4*REG_R13)
STMIA r3!, {sp, lr}
CPS #SVC_MODE
ADD r1, r1, #XCPTCONTEXT_SIZE
portMPU_RegisterSave
PUSH {lr}
LDR r0, arch_clean_invalidate_dcache_all_const
BLX r0
POP {lr}
POP {r0-r3, r12}
MOVS pc, lr
.endm
; /**********************************************************************/
.macro portCPU_RegisterRestore
#if CONFIG_ARCH_WITH_FPU
ADD r3, r1, #(4*REG_S0)
VLDMIA r3!, {s0-s31}
LDR r2, [r3], #4
VMSR fpscr, r2
#endif
ADD r4, r1, #(4*REG_R15)
LDMIA r4, {r2, r3}
MOV lr, r2
MSR SPSR_cxsf, r3
CPS #SYS_MODE
ADD r4, r1, #(4*REG_R13)
LDMIA r4, {r2, r3}
MOV sp, r2
MOV lr, r3
PUSH {lr}
MOV lr, r1
ADD r1, r1, #XCPTCONTEXT_SIZE
portMPU_RegisterRestore
LDMIA lr, {r0-r12}
POP {lr}
CPS #SVC_MODE
MOVS pc, lr
.endm

View File

@@ -0,0 +1,63 @@
/*
* arm_atomic.s
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM atomic function.
*
* Revision History:
* -----------------
* 2021-09-08 Wanghao.Xu Export function symbols
*/
INCLUDE config.h
INCLUDE compiler.h
PUBLIC arch_atomic_swap
PUBLIC arch_atomic_add
PUBLIC arch_atomic_and
PUBLIC arch_atomic_or
SECTION .text:CODE(2)
arch_atomic_swap:
.Lloop_atomic_swap:
ldrex r12, [r0]
strex r2, r1, [r0]
cmp r2, #0
bne .Lloop_atomic_swap
mov r0, r12
bx lr
arch_atomic_add:
.Lloop_atomic_add:
ldrex r12, [r0]
add r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_add
mov r0, r12
bx lr
arch_atomic_and:
.Lloop_atomic_and:
ldrex r12, [r0]
and r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_and
mov r0, r12
bx lr
arch_atomic_or:
.Lloop_atomic_or:
ldrex r12, [r0]
orr r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .Lloop_atomic_or
mov r0, r12
bx lr
END

View File

@@ -0,0 +1,324 @@
/*
* Copyright (c) 2008-2012 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
INCLUDE config.h
INCLUDE compiler.h
INCLUDE armv7-r/cache.h
#if CONFIG_ARCH_WITH_CACHE
PUBLIC arch_disable_cache
PUBLIC arch_enable_cache
PUBLIC arch_clean_cache_range
PUBLIC arch_clean_invalidate_cache_range
PUBLIC arch_clean_invalidate_dcache_all
PUBLIC arch_invalidate_cache_range
PUBLIC arch_sync_cache_range
SECTION .text:CODE(2)
/* void arch_disable_cache(uint flags) */
arch_disable_cache:
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r8, cpsr // save the old interrupt state
cpsid iaf // interrupts disabled
.Ldcache_disable:
tst r7, #DCACHE
beq .Licache_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already disabled?
beq .Ldcache_already_disabled
bic r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // disable dcache
// flush and invalidate the dcache
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl flush_invalidate_cache_v7
b .Ldcache_disable_L2
.Ldcache_already_disabled:
// make sure all of the caches are invalidated
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
.Ldcache_disable_L2:
#if CONFIG_ARCH_L2CACHE
// disable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
bic r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
#endif
.Licache_disable:
tst r7, #ICACHE
beq .Ldone_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
bic r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // disable icache
.Ldone_disable:
// make sure the icache is always invalidated
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
msr cpsr_cxsf, r8
ldmfd sp!, {r4-r11, pc}
/* void arch_enable_cache(uint flags) */
arch_enable_cache:
stmfd sp!, {r4-r12, lr}
mov r7, r0 // save flags
mrs r8, cpsr // save the old interrupt state
cpsid iaf // interrupts disabled
.Ldcache_enable:
tst r7, #DCACHE
beq .Licache_enable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
// invalidate L1 and L2
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
#if CONFIG_ARCH_L2CACHE
// enable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
orr r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
#endif
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // enable dcache
.Licache_enable:
tst r7, #ICACHE
beq .Ldone_enable
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // enable icache
.Ldone_enable:
isb
msr cpsr_cxsf, r8
ldmfd sp!, {r4-r12, pc}
// flush & invalidate cache routine, trashes r0-r6, r9-r11
flush_invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
dmb
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished
MOV R10, #0
.Loop1:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
isb // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3
SUBS R6, R6, #1 // decrement the index
BGE .Loop2
.Lskip:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1
.Lfinished:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
dsb
isb
bx lr
// invalidate cache routine, trashes r0-r6, r9-r11
invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
dmb
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished_invalidate
MOV R10, #0
.Loop1_invalidate:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip_invalidate // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
isb // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2_invalidate:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3_invalidate:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3_invalidate
SUBS R6, R6, #1 // decrement the index
BGE .Loop2_invalidate
.Lskip_invalidate:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1_invalidate
.Lfinished_invalidate:
dsb
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
isb
bx lr
/* void arch_flush_cache_range(addr_t start, size_t len); */
arch_clean_cache_range:
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
.Loop_clean:
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
add r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo .Loop_clean
dsb
#endif
bx lr
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
arch_clean_invalidate_cache_range:
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
.Loop_clean_invalidate:
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate dcache to PoC by MVA
add r0, r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo .Loop_clean_invalidate
dsb
#endif
bx lr
/* void arch_clean_invalidate_dcache_all(void); */
arch_clean_invalidate_dcache_all:
#if CONFIG_ARM_WITH_CP15
mrc p15, 1, r0, c0, c0, 0 /* Read the Cache Size Identification Register */
ldr r3, =0x7fff /* Isolate the NumSets field (bits 13-27) */
and r0, r3, r0, lsr #13 /* r0=NumSets (number of sets - 1) */
mov r1, #0 /* r1 = way loop counter */
way_loop:
mov r3, #0 /* r3 = set loop counter */
set_loop:
mov r2, r1, lsl #30 /* r2 = way loop counter << 30 */
orr r2, r3, lsl #5 /* r2 = set/way cache operation format */
mcr p15, 0, r2, c7, c14, 2 /* Data Cache Clean Invalidate by Set/Way */
add r3, r3, #1 /* Increment set counter */
cmp r0, r3 /* Last set? */
bge set_loop /* Keep looping if not */
add r1, r1, #1 /* Increment the way counter */
cmp r1, #4 /* Last way? (four ways assumed) */
bne way_loop /* Keep looping if not */
dsb
#endif
bx lr
/* void arch_invalidate_cache_range(addr_t start, size_t len); */
arch_invalidate_cache_range:
#if CONFIG_ARM_WITH_CP15
mov r3, r0 // save the start address
add r2, r0, r1 // calculate the end address
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
.Loop_invalidate:
mcr p15, 0, r0, c7, c6, 1 // invalidate dcache to PoC by MVA
add r0, r0, #CONFIG_ARCH_CACHE_LINE
cmp r0, r2
blo .Loop_invalidate
dsb
#endif
bx lr
/* void arch_sync_cache_range(addr_t start, size_t len); */
arch_sync_cache_range:
push { r14 }
bl arch_clean_cache_range
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
pop { pc }
#endif
END

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2008-2015 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
INCLUDE config.h
INCLUDE compiler.h
EXTERN arm_undefined_handler
EXTERN arm_prefetch_abort_handler
EXTERN arm_data_abort_handler
EXTERN arm_irq_handler
EXTERN arm_fiq_handler
PUBLIC Arm_Undefined_Handler
PUBLIC Arm_SWI_Handler
PUBLIC Arm_Prefetch_Handler
PUBLIC Arm_Abort_Handler
PUBLIC Arm_IRQ_Handler
PUBLIC Arm_FIQ_Handler
PUBLIC arm_save_mode_regs
PUBLIC arm_reserved
SECTION .text:CODE:ROOT(2)
; macros to align and unalign the stack on 8 byte boundary for ABI compliance
stack_align macro tempreg
; make sure the stack is aligned
mov tempreg, sp
tst sp, #4
subeq sp, #4
push { tempreg }
; tempreg holds the original stack
endm
stack_restore macro tempreg
; restore the potentially unaligned stack
pop { tempreg }
mov sp, tempreg
endm
; save and disable the vfp unit
vfp_save macro temp1
; save old fpexc
vmrs temp1, fpexc
push { temp1 }
; hard disable the vfp unit
bic temp1, #(1<<30)
vmsr fpexc, temp1
endm
; restore the vfp enable/disable state
vfp_restore macro temp1
; restore fpexc
pop { temp1 }
vmsr fpexc, temp1
endm
; Save callee trashed registers.
; At exit r0 contains a pointer to the register frame.
save macro
; save spsr and r14 onto the svc stack
srsdb #0x13!
; switch to svc mode, interrupts disabled
cpsid i,#0x13
; save callee trashed regs and lr
push { r0-r4, r12, lr }
; save user space sp/lr
sub sp, #8
stmia sp, { r13, r14 }^
#if CONFIG_ARCH_WITH_FPU
; save and disable the vfp unit
vfp_save r0
#endif
; make sure the stack is 8 byte aligned
stack_align r0
; r0 now holds the pointer to the original iframe (before alignment)
endm
save_offset macro offset
sub lr, offset
save
endm
restore macro
; undo the stack alignment we did before
stack_restore r0
#if CONFIG_ARCH_WITH_FPU
; restore the old state of the vfp unit
vfp_restore r0
#endif
; restore user space sp/lr
ldmia sp, { r13, r14 }^
add sp, #8
pop { r0-r4, r12, lr }
; return to whence we came from
rfeia sp!
endm
; Save all registers.
; At exit r0 contains a pointer to the register frame.
saveall macro
; save spsr and r14 onto the svc stack
srsdb #0x13!
; switch to svc mode, interrupts disabled
cpsid i,#0x13
; save all regs
push { r0-r12, lr }
; save user space sp/lr
sub sp, #8
stmia sp, { r13, r14 }^
#if CONFIG_ARCH_WITH_FPU
; save and disable the vfp unit
vfp_save r0
#endif
; make sure the stack is 8 byte aligned
stack_align r0
; r0 now holds the pointer to the original iframe (before alignment)
endm
saveall_offset macro offset
sub lr, offset
saveall
endm
restoreall macro
; undo the stack alignment we did before
stack_restore r0
#if CONFIG_ARCH_WITH_FPU
; restore the old state of the vfp unit
vfp_restore r0
#endif
; restore user space sp/lr
ldmia sp, { r13, r14 }^
add sp, #8
pop { r0-r12, r14 }
; return to whence we came from
rfeia sp!
endm
arm_save_mode_regs:
mrs r1, cpsr
stmia r0, { r13, r14 }^ /* usr */
add r0, #8
cps #0x11 /* fiq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x12 /* irq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x13 /* svc */
str r13, [r0], #4
str r14, [r0], #4
cps #0x17 /* abt */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1b /* und */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1f /* sys */
str r13, [r0], #4
str r14, [r0], #4
msr cpsr_c, r1
bx lr
Arm_Undefined_Handler:
save
; r0 now holds pointer to iframe
bl arm_undefined_handler
restore
Arm_Prefetch_Handler:
saveall_offset #4
; r0 now holds pointer to iframe
bl arm_prefetch_abort_handler
restoreall
Arm_Abort_Handler:
saveall_offset #8
; r0 now holds pointer to iframe
bl arm_data_abort_handler
restoreall
Arm_SWI_Handler:
/* not support */
ldr r0,=Arm_SWI_Handler
bx r0
Arm_IRQ_Handler:
sub lr, lr, #4
srsdb #0x13!
cpsid i,#0x13
push {r0-r4, r12, lr}
sub sp, #8
stmia sp, {r13, r14}^
mov r2, sp
tst sp, #4
subeq sp, #4
push {r2}
push {r0, lr}
bl arm_irq_handler
pop {r0, lr}
pop {r2}
mov sp, r2
ldmia sp, {r13, r14}^
add sp, #8
pop {r0-r4, r12, lr}
rfeia sp!
Arm_FIQ_Handler:
push {r0-r3, r12, lr}
blx arm_fiq_handler
pop {r0-r3, r12, lr}
subs pc, lr, #4
arm_reserved:
b .
END

View File

@@ -0,0 +1,43 @@
/*
* arm_fullcontextrestore.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM full context restore.
*
* Revision History:
* -----------------
*/
INCLUDE config.h
INCLUDE compiler.h
INCLUDE armv7-r/svcall.h
/****************************************************************************
* Public Functions
****************************************************************************/
PUBLIC arm_fullcontextrestore
SECTION .text:CODE(2)
/****************************************************************************
* Name: arm_fullcontextrestore
****************************************************************************/
arm_fullcontextrestore:
cps #0x1F /* Enter sys mode */
/* Perform the System call with R0=1 and R1=regs */
mov r1, r0 /* R1: regs */
mov r0, #SYS_restore_context /* R0: restore context */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
/* This call should not return */
bx lr /* Unnecessary ... will not return */
END

View File

@@ -0,0 +1,39 @@
/*
* arm_saveusercontext.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM save user context.
*
* Revision History:
* -----------------
*/
INCLUDE config.h
INCLUDE compiler.h
INCLUDE armv7-r/svcall.h
/****************************************************************************
* Public Functions
****************************************************************************/
PUBLIC arm_saveusercontext
SECTION .text:CODE(2)
/****************************************************************************
* Name: arm_saveusercontext
****************************************************************************/
arm_saveusercontext:
/* Perform the System call with R0=0 and R1=regs */
mov r1, r0 /* R1: regs */
mov r0, #SYS_save_context /* R0: save context (also return value) */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
bx lr
END

View File

@@ -0,0 +1,40 @@
/*
* arm_switchcontext.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM switch context.
*
* Revision History:
* -----------------
*/
INCLUDE config.h
INCLUDE compiler.h
INCLUDE armv7-r/svcall.h
/****************************************************************************
* Public Functions
****************************************************************************/
PUBLIC arm_switchcontext
SECTION .text:CODE(2)
/****************************************************************************
* Name: arm_switchcontext
****************************************************************************/
arm_switchcontext:
/* Perform the System call with R0=2 */
mov r0, #SYS_switch_context /* R0: context switch */
svc 0 /* Force synchronous SVCall (or Hard Fault) */
/* We will get here only after the rerturn from the context switch */
bx lr
END

View File

@@ -0,0 +1,127 @@
/*
* arm_tcm.S
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R TCM driver.
*
* Revision History:
* -----------------
*/
INCLUDE config.h
INCLUDE compiler.h
INCLUDE armv7-r/tcm.h
#if CONFIG_ARM_WITH_TCM
PUBLIC tcma_enable_early
PUBLIC tcmb_enable_early
SECTION .text:CODE(2)
tcm_enable MACRO idx addr_reg temp_reg
orr temp_reg, addr_reg, #1
mcr p15, 0, temp_reg, c9, c1, idx
ENDM
tcm_enable_ecc MACRO temp_reg val
mrc p15, 0, temp_reg, c1, c0, 1
orr temp_reg, temp_reg, #(val)
mcr p15, 0, temp_reg, c1, c0, 1
ENDM
tcm_disable_ecc MACRO temp_reg val
mrc p15, 0, temp_reg, c1, c0, 1
bic temp_reg, temp_reg, #(val)
mcr p15, 0, temp_reg, c1, c0, 1
ENDM
tcm_get_size MACRO idx size_reg temp_reg
mrc p15, 0, size_reg, c9, c1, idx
ubfx size_reg, size_reg, #2, #5
adds size_reg, #9
movs temp_reg, #1
lsls size_reg, temp_reg, size_reg
ENDM
tcm_clear MACRO addr_reg size_reg temp_reg1 temp_reg2
local .Ltcm_loop
local .Ltcm_loop_end
mov temp_reg1, #0
mov temp_reg2, #0
add size_reg, addr_reg, size_reg
.Ltcm_loop:
cmp addr_reg, size_reg
bhs .Ltcm_loop_end
stmia addr_reg!, {temp_reg1-temp_reg2}
b .Ltcm_loop
.Ltcm_loop_end:
ENDM
/* This function not store registers,
* only used before stack setup.
*/
tcma_enable_early:
/* disable ecc */
tcm_disable_ecc r4, ATCMPCEN
/* read tcma size, r2 save size */
tcm_get_size 1, r2, r4
/* enable tcma, r0 save addr */
tcm_enable 1, r0, r4
/* check enable ecc */
cmp r1, #1
bne .Lout
/* clear tcma */
tcm_clear r0, r2, r6, r7
/* enalbe ecc */
tcm_enable_ecc r4, ATCMPCEN
b .Lout
/* This function not store registers,
* only used before stack setup.
*/
tcmb_enable_early:
/* disable ecc */
tcm_disable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
/* read tcma size, r2 save size */
tcm_get_size 0, r2, r4
/* enable tcma, r0 save addr */
tcm_enable 0, r0, r4
/* check enable ecc */
cmp r1, #1
bne .Lout
/* clear tcma */
tcm_clear r0, r2, r6, r7
/* enalbe ecc */
tcm_enable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
b .Lout
/* Clear the TCM, each store must be 64 bits aligned. */
tcm_clear_64bit:
push {r6, r7}
tcm_clear r0, r1, r6, r7
pop {r6, r7}
.Lout:
bx lr
#endif
END

View File

@@ -0,0 +1,134 @@
/*
* context_saverestore.S
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description:
*
* Revision History:
* -----------------
*/
portMPU_RegisterSave MACRO
MOV r0, #0
mpu_save_loop:
MCR p15, 0, r0, c6, c2, 0
MRC p15, 0, r2, c6, c1, 0
STR r2, [r1], #4
MRC p15, 0, r2, c6, c1, 4
STR r2, [r1], #4
MRC p15, 0, r2, c6, c1, 2
STR r2, [r1], #4
ADD r0, r0, #1
CMP r0, #16
BNE mpu_save_loop
MRC p15, 0, r2, c1, c0, 0
STR r2, [r1], #4
ENDM
; /**********************************************************************/
portMPU_RegisterRestore MACRO
MRC p15, 0, r2, c1, c0, 0
LDR r0, =(SCTLR_BR | SCTLR_M)
BIC r2, r2, r0
MCR p15, 0, r2, c1, c0, 0
MOV r0, #0
mpu_restore_loop:
MCR p15, 0, r0, c6, c2, 0
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 0
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 4
LDR r2, [r1], #4
MCR p15, 0, r2, c6, c1, 2
ADD r0, r0, #1
CMP r0, #16
BNE mpu_restore_loop
MRC p15, 0, r0, c1, c0, 0
LDR r2, =(SCTLR_BR | SCTLR_M)
ORR r0, r0, r2
LDR r2, [r1], #4
TST r2, #SCTLR_M
MCRNE p15, 0, r0, c1, c0, 0
ENDM
; /**********************************************************************/
portCPU_RegisterSave MACRO
PUSH {r0-r3, r12}
STMIA r1, {r0-r12}
STR lr, [r1, #(4*REG_R15)]
MRS r2, SPSR
STR r2, [r1, #(4*REG_CPSR)]
#if CONFIG_ARCH_WITH_FPU
ADD r3, r1, #(4*REG_S0)
VSTMIA r3!, {s0-s31}
VMRS r2, fpscr
STR r2, [r3], #4
#endif
CPS #SYS_MODE
ADD r3, r1, #(4*REG_R13)
STMIA r3!, {sp, lr}
CPS #SVC_MODE
ADD r1, r1, #XCPTCONTEXT_SIZE
portMPU_RegisterSave
PUSH {lr}
LDR r0, arch_clean_invalidate_dcache_all_const
BLX r0
POP {lr}
POP {r0-r3, r12}
MOVS pc, lr
ENDM
; /**********************************************************************/
portCPU_RegisterRestore MACRO
#if CONFIG_ARCH_WITH_FPU
ADD r3, r1, #(4*REG_S0)
VLDMIA r3!, {s0-s31}
LDR r2, [r3], #4
VMSR fpscr, r2
#endif
ADD r4, r1, #(4*REG_R15)
LDMIA r4, {r2, r3}
MOV lr, r2
MSR SPSR_cxsf, r3
CPS #SYS_MODE
ADD r4, r1, #(4*REG_R13)
LDMIA r4, {r2, r3}
MOV sp, r2
MOV lr, r3
PUSH {lr}
MOV lr, r1
ADD r1, r1, #XCPTCONTEXT_SIZE
portMPU_RegisterRestore
LDMIA lr, {r0-r12}
POP {lr}
CPS #SVC_MODE
MOVS pc, lr
ENDM

View File

@@ -0,0 +1,77 @@
/*
* arm.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARMV7R common register interface.
*
* Revision History:
* -----------------
*/
#ifndef ARMV7R_ARM_H
#define ARMV7R_ARM_H
#define MODE_USR 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_ABT 0x17
#define MODE_UND 0x1B
#define MODE_SYS 0x1F
#define MODE_MASK 0x1F
/* SCTLR */
#define SCTLR_M (1 << 0)
#define SCTLR_A (1 << 1)
#define SCTLR_C (1 << 2)
#define SCTLR_CCP15BEN (1 << 5)
#define SCTLR_B (1 << 7)
#define SCTLR_SW (1 << 10)
#define SCTLR_Z (1 << 11)
#define SCTLR_I (1 << 12)
#define SCTLR_V (1 << 13)
#define SCTLR_RR (1 << 14)
#define SCTLR_BR (1 << 17)
#define SCTLR_DZ (1 << 19)
#define SCTLR_FI (1 << 21)
#define SCTLR_U (1 << 22)
#define SCTLR_VE (1 << 24)
#define SCTLR_EE (1 << 25)
#define SCTLR_NMFI (1 << 27)
#define SCTLR_TE (1 << 30)
#define SCTLR_IE (1 << 31)
/* PSR */
#define PSR_MODE_SHIFT (0)
#define PSR_MODE_MASK (0x1f << PSR_MODE_SHIFT)
#define PSR_MODE_USR (MODE_USR << PSR_MODE_SHIFT)
#define PSR_MODE_FIQ (MODE_FIQ << PSR_MODE_SHIFT)
#define PSR_MODE_IRQ (MODE_IRQ << PSR_MODE_SHIFT)
#define PSR_MODE_SVC (MODE_SVC << PSR_MODE_SHIFT)
#define PSR_MODE_ABT (MODE_ABT << PSR_MODE_SHIFT)
#define PSR_MODE_UND (MODE_UND << PSR_MODE_SHIFT)
#define PSR_MODE_SYS (MODE_SYS << PSR_MODE_SHIFT)
#define PSR_T_BIT (1 << 5)
#define PSR_F_BIT (1 << 6)
#define PSR_I_BIT (1 << 7)
#define PSR_A_BIT (1 << 8)
#define PSR_E_BIT (1 << 9)
#define PSR_IT27_SHIFT (10)
#define PSR_IT27_MASK (0x3f << PSR_IT27_SHIFT)
#define PSR_GE_SHIFT (16)
#define PSR_GE_MASK (15 << PSR_GE_SHIFT)
#define PSR_J_BIT (1 << 24)
#define PSR_IT01_SHIFT (25)
#define PSR_IT01_MASK (3 << PSR_IT01_SHIFT)
#define PSR_Q_BIT (1 << 27)
#define PSR_V_BIT (1 << 28)
#define PSR_C_BIT (1 << 29)
#define PSR_Z_BIT (1 << 30)
#define PSR_N_BIT (1 << 31)
#endif

View File

@@ -0,0 +1,62 @@
/*
* atomic.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM atomic interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_ATOMIC_H
#define INCLUDE_ARCH_ATOMIC_H
#ifndef ASSEMBLY
#include <compiler.h>
__BEGIN_CDECLS
/*
* atomic swap.
*
* @ptr address of data A.
* @val value of data B.
* @return old value of data A.
*/
int arch_atomic_swap(int *ptr, int val);
/*
* atomic add.
*
* @ptr address of data A.
* @val value of data B.
* @return old value of data A.
*/
int arch_atomic_add(int *ptr, int val);
/*
* atomic and.
*
* @ptr address of data A.
* @val value of data B.
* @return old value of data A.
*/
int arch_atomic_and(int *ptr, int val);
/*
* atomic or.
*
* @ptr address of data A.
* @val value of data B.
* @return old value of data A.
*/
int arch_atomic_or(int *ptr, int val);
__END_CDECLS
#endif
#endif

View File

@@ -0,0 +1,22 @@
/*
* barriers.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARMV7R barriers interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_ARMV7R_BARRIERS_H
#define INCLUDE_ARCH_ARMV7R_BARRIERS_H
#include <compiler.h>
#define DSB __ASM volatile("dsb" ::: "memory")
#define DMB __ASM volatile("dmb" ::: "memory")
#define ISB __ASM volatile("isb" ::: "memory")
#endif

View File

@@ -0,0 +1,113 @@
/*
* cache.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM cache interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_CACHE_H
#define INCLUDE_ARCH_CACHE_H
#define ICACHE 1
#define DCACHE 2
#define UCACHE (ICACHE|DCACHE)
#define __CACHE_ALIGN __ALIGNED(CONFIG_ARCH_CACHE_LINE)
#ifndef ASSEMBLY
#include <types.h>
#include <compiler.h>
__BEGIN_CDECLS
/*
* enable caches.
*
* @flags cache type.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_enable_cache(uint8_t flags);
#else
#define arch_enable_cache(flags)
#endif
/*
* disable caches.
*
* @flags cache type.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_disable_cache(uint8_t flags);
#else
#define arch_disable_cache(flags)
#endif
/*
* clean dcache.
*
* @start start address.
* @len clean data length.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_clean_cache_range(addr_t start, size_t len);
#else
#define arch_clean_cache_range(start, len)
#endif
/*
* clean and invalidate dcache.
*
* @start start address.
* @len clean data length.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_clean_invalidate_cache_range(addr_t start, size_t len);
#else
#define arch_clean_invalidate_cache_range(start, len)
#endif
/*
* clean and invalidate dcache all
*
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_clean_invalidate_dcache_all(void);
#else
#define arch_clean_invalidate_dcache_all()
#endif
/*
* invalidate dcache.
*
* @start start address.
* @len clean data length.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_invalidate_cache_range(addr_t start, size_t len);
#else
#define arch_invalidate_cache_range(start, len)
#endif
/*
* sync dcache.
*
* @start start address.
* @len clean data length.
*/
#if CONFIG_ARCH_WITH_CACHE
void arch_sync_cache_range(addr_t start, size_t len);
#else
#define arch_sync_cache_range(start, len)
#endif
__END_CDECLS
#endif
#endif

View File

@@ -0,0 +1,64 @@
/*
* exceptions.h
*
* Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARMV7R exceptions interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_ARMV7R_EXCEPTIONS_H
#define INCLUDE_ARCH_ARMV7R_EXCEPTIONS_H
struct arm_iframe {
#if CONFIG_ARCH_WITH_FPU
uint32_t fpexc;
#endif
uint32_t usp;
uint32_t ulr;
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r12;
uint32_t lr;
uint32_t pc;
uint32_t spsr;
};
struct arm_fault_frame {
#if CONFIG_ARCH_WITH_FPU
uint32_t fpexc;
#endif
uint32_t usp;
uint32_t ulr;
uint32_t r[13];
uint32_t lr;
uint32_t pc;
uint32_t spsr;
};
struct arm_mode_regs {
uint32_t usr_r13, usr_r14;
uint32_t fiq_r13, fiq_r14;
uint32_t irq_r13, irq_r14;
uint32_t svc_r13, svc_r14;
uint32_t abt_r13, abt_r14;
uint32_t und_r13, und_r14;
uint32_t sys_r13, sys_r14;
};
void arm_save_mode_regs(struct arm_mode_regs *regs);
void Arm_Undefined_Handler(void);
void Arm_Prefetch_Handler(void);
void Arm_Abort_Handler(void);
void Arm_SWI_Handler(void);
void Arm_IRQ_Handler(void);
void Arm_FIQ_Handler(void);
void arm_reserved(void);
#endif

View File

@@ -0,0 +1,44 @@
/*
* fpu.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM fpu interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_FPU_H
#define INCLUDE_ARCH_FPU_H
#ifndef ASSEMBLY
#include <compiler.h>
__BEGIN_CDECLS
/*
* fpu enable.
*/
#if CONFIG_ARCH_WITH_FPU
void arm_fpu_enable(void);
#else
#define arm_fpu_enable()
#endif
/*
* fpu disable.
*/
#if CONFIG_ARCH_WITH_FPU
void arm_fpu_disable(void);
#else
#define arm_fpu_disable()
#endif
__END_CDECLS
#endif
#endif

114
arch/include/armv7-r/irq.h Normal file
View File

@@ -0,0 +1,114 @@
/*
* irq.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM irq interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_IRQ_H
#define INCLUDE_ARCH_IRQ_H
#ifndef ASSEMBLY
#include <compiler.h>
#include <stdbool.h>
__BEGIN_CDECLS
/*
* irq state type.
*/
typedef unsigned int irq_state_t;
/*
* irq enable.
*/
static inline void arch_irq_enable(void)
{
CF;
__ASM volatile("cpsie i");
}
/*
* irq disable.
*/
static inline void arch_irq_disable(void)
{
__ASM volatile("cpsid i");
CF;
}
/*
* irq save.
*
* @return old irq state.
*/
static inline irq_state_t arch_irq_save(void)
{
unsigned int cpsr;
__ASM volatile
(
"\tmrs %0, cpsr\n"
"\tcpsid i\n"
: "=r" (cpsr)
:
: "memory"
);
return cpsr;
}
/*
* irq restore.
*
* @flags old irq state.
*/
static inline void arch_irq_restore(irq_state_t flags)
{
__ASM volatile
(
"msr cpsr_c, %0"
:
: "r" (flags)
: "memory"
);
}
/*
* is irq masked.
*
* @return masked or not.
*/
bool arch_irq_is_masked(void);
/*
* is irq mode.
*
* @return irq mode or not.
*/
bool arch_in_irq_mode(void);
/**
* @brief Enable vectored interrupt mode.
*/
void arch_vectored_irq_enable(bool en);
/**
* @brief Whether core is in FIQ mode or not
*
* @return true FIQ mode
* @return false otherwise
*/
bool arch_in_fiq_mode(void);
__END_CDECLS
#endif
#endif

106
arch/include/armv7-r/mpu.h Normal file
View File

@@ -0,0 +1,106 @@
/*
* mpu.h
*
* Copyright (c) 2019 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R MPU driver.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_ARMV7R_MPU_H
#define INCLUDE_ARCH_ARMV7R_MPU_H
/*
* Memory types supported by the MPU driver.
*/
typedef enum mpu_region_type {
/* Strong ordered
* - non-bufferable, non-cachable, shareable, RW, XN
*/
MPU_REGION_STRONGORDERED,
/* Device memory
* - bufferable, non-cachable, shareable, RW, XN
*/
MPU_REGION_DEVICE,
/* Normal memory
* - bufferable, outer and inner write-back & write allocate,
* shareble, RW, non XN
*/
MPU_REGION_NORMAL,
/* Normal non-cacheable memory
* - bufferable, outer and inner non-cacheable, shareble, RW,
* non XN
*/
MPU_REGION_NORMAL_NONCACHEABLE,
/* Normal ready-only memory
* - bufferable, outer and inner wb, no wa, no shareble, RO,
* non XN
*/
MPU_REGION_NORMAL_RO,
/* Not accessable.
*/
MPU_REGION_NO_ACCESS,
MPU_REGION_MAX,
} mpu_region_type_e;
#ifndef ASSEMBLY
#include <compiler.h>
#include <stdbool.h>
#include <types.h>
typedef struct mpu_config {
addr_t addr;
uint64_t size;
mpu_region_type_e type;
} mpu_config_t;
__BEGIN_CDECLS
#if CONFIG_ARCH_WITH_MPU
void mpu_clear_region(void);
#else
#define mpu_clear_region()
#endif
#if CONFIG_ARCH_WITH_MPU
void mpu_add_region(int region, uint32_t base, uint64_t size,
mpu_region_type_e type);
#else
#define mpu_add_region(region, base, size, type)
#endif
uint32_t mpu_region_index(void);
#if CONFIG_ARCH_WITH_MPU
void mpu_enable(bool enable);
#else
#define mpu_enable(enable)
#endif
#if CONFIG_ARCH_WITH_MPU
bool mpu_is_belong_uncache_region(uint32_t base, uint32_t size);
#else
#define mpu_is_belong_uncache_region(base, size)
#endif
#if CONFIG_ARCH_WITH_MPU
void mpu_region_set_type(uint32_t base, uint64_t size,
mpu_region_type_e type);
#else
#define mpu_region_set_type(base, size, type)
#endif
__END_CDECLS
#endif /* ASSEMBLY */
#endif

206
arch/include/armv7-r/pmu.h Normal file
View File

@@ -0,0 +1,206 @@
/*
* pmu.h
*
* Copyright (c) 2019 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R Performance Monitor driver.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_PMU_H
#define INCLUDE_ARCH_PMU_H
#include <types.h>
#include <armv7-r/register.h>
typedef enum pmu_evt_cntr {
PMU_EVT_COUNTER1 = 0,
PMU_EVT_COUNTER2 = 1,
PMU_EVT_COUNTER3 = 2,
} pmu_evt_cntr_e;
typedef enum pmu_evt {
PMU_EVT_SOFTWARE_INCREMENT = 0x0,
PMU_EVT_ICACHE_MISS = 0x1,
PMU_EVT_DCACHE_MISS = 0x3,
PMU_EVT_DCACHE_ACCESS = 0x4,
PMU_EVT_DATA_READ = 0x6,
PMU_EVT_DATA_WRITE = 0x7,
PMU_EVT_INSTRUCTION_EXECUTED = 0x8,
PMU_EVT_DUAL_ISSUED_INSTUCTIONS = 0x5e,
PMU_EVT_EXECPTION_TAKEN = 0x9,
PMU_EVT_EXECPTION_RETURN = 0xa,
PMU_EVT_CHANGE_CONTEXT_ID = 0xb,
PMU_EVT_SW_CHANGE_PC = 0xc,
PMU_EVT_BRANCH_IMMEDIATE = 0xd,
PMU_EVT_PROCEDURE_RETURN = 0xe,
PMU_EVT_UNALIGNED_ACCESS = 0xf,
PMU_EVT_BRANCH_NOT_PREDICTED = 0x10,
PMU_EVT_CYCLE_CNT = 0x11,
PMU_EVT_BRANCH_PREDICTED = 0x12,
PMU_EVT_STALL_INSTRUCTION = 0x40,
PMU_EVT_STALL_DATA_DEPENDENCY = 0x41,
PMU_EVT_DCACHE_WRITE_BACK = 0x42,
PMU_EVT_EXT_MEMORY_REQ = 0x43,
PMU_EVT_STALL_LSU_BUSY = 0x44,
PMU_EVT_DRAIN_STORE_BUFFER = 0x45,
PMU_EVT_FIQ_DISABLE_CYCLES = 0x46,
PMU_EVT_IRQ_DISABLE_CYCLES = 0x47,
PMU_EVT_ETMEXTOUTM0 = 0x48,
PMU_EVT_ETMEXTOUTM1 = 0x49,
PMU_EVT_ICACHE_TAG_ECCERR = 0x4a,
PMU_EVT_ICACHE_DATA_ECCERR = 0x4b,
PMU_EVT_DCACHE_TAG_ECCERR = 0x4c,
PMU_EVT_DCACHE_DATA_ECCERR = 0x4d,
PMU_EVT_TCM_ECCERR_PFU = 0x4e,
PMU_EVT_TCM_ECCERR_LSU = 0x4f,
PMU_EVT_STORE_BUFFER_MERGE = 0x50,
PMU_EVT_LSU_STALL_BY_STORE_BUFFER = 0x51,
PMU_EVT_LSU_STALL_BY_STORE_QUEUE = 0x52,
PMU_EVT_INT_DIV = 0x53,
PMU_EVT_STALL_CYCLE_BY_INT_DIV = 0x54,
PMU_EVT_PLD_LINEFILL = 0x55,
PMU_EVT_PLD_NO_LINEFILL = 0x56,
PMU_EVT_NON_CACHEABLE_AXI_ACCESS = 0x57,
PMU_EVT_ICACHE_ACCESS = 0x58,
PMU_EVT_STORE_BUFFER_SLOT_ATTR_CONFLICT = 0x59,
PMU_EVT_DUAL_ISSUE_CASE_A = 0x5a,
PMU_EVT_DUAL_ISSUE_CASE_B1_B2_F2_F2D = 0x5b,
PMU_EVT_DUAL_ISSUE_CASE_OTHER = 0x5c,
PMU_EVT_DOUBLE_PRECISION_FLOAT_EXEC = 0x5d,
PMU_EVT_DCACHE_DATA_FATAL_ECCERR = 0x60,
PMU_EVT_DCACHE_TAG_FATAL_ECCERR = 0x61,
PMU_EVT_PROCESSOR_LIVELOCK = 0x62,
PMU_EVT_ATCM_MB_ECCERR = 0x64,
PMU_EVT_B0TCM_MB_ECCERR = 0x65,
PMU_EVT_B1TCM_MB_ECCERR = 0x66,
PMU_EVT_ATCM_SB_ECCERR = 0x67,
PMU_EVT_B0TCM_SB_ECCERR = 0x68,
PMU_EVT_B1TCM_SB_ECCERR = 0x69,
PMU_EVT_TCM_CORRECTABLE_ECCERR_LSU = 0x6a,
PMU_EVT_TCM_CORRECTABLE_ECCERR_PFU = 0x6b,
PMU_EVT_TCM_FATAL_ECCERR_AXI_SLAVE = 0x6c,
PMU_EVT_TCM_CORRECTABLE_ECCERR_AXI_SLAVE = 0x6d,
PMU_EVT_CORRECTABLE_EVENTS = 0x6e,
PMU_EVT_FATAL_EVENTS = 0x6f,
PMU_EVT_CORRECTABLE_BUS_FAULTS = 0x70,
PMU_EVT_FATAL_BUS_FAULTS = 0x71,
PMU_EVT_ACP_DCACHE_ACCESS = 0x72,
PMU_EVT_ACP_DCACHE_INVALIDATE = 0x73,
} pmu_evt_e;
#define PMCR_E (1 << 0) /* pmu enable */
#define PMCR_P (1 << 1) /* event counter reset */
#define PMCR_C (1 << 2) /* cycle counter reset */
#define PMCR_D (1 << 3) /* count every 64 clock cycles */
#if CONFIG_ARM_WITH_PMU
/* Enable the PMU. All counters are cleared. */
static inline void pmu_enable(void)
{
uint32_t val = arm_read_pmcr();
val |= PMCR_P | PMCR_C | PMCR_E;
arm_write_pmcr(val);
}
/* Diable the PMU. All counters are cleared. */
static inline void pmu_disable(void)
{
uint32_t val = arm_read_pmcr();
val &= ~(PMCR_P | PMCR_C | PMCR_E);
arm_write_pmcr(val);
}
/* Get cycle counter enable status */
static inline bool pmu_cycle_cntr_status(void)
{
uint32_t val = arm_read_pmcntenset();
return !!(val & (1U << 31));
}
/* Start cycle counter. Set div64 = true to count every
* 64 clock cycles.
*/
static inline void pmu_start_cycle_cntr(bool div64)
{
uint32_t val = arm_read_pmcr();
if (div64)
val |= PMCR_D;
else
val &= ~PMCR_D;
arm_write_pmcr(val);
arm_write_pmcntenset(1U << 31);
}
/* Stop cycle counter. */
static inline void pmu_stop_cycle_cntr(void)
{
arm_write_pmcntenclr(1U << 31);
}
/* Stop and clear the cycle counter. */
static inline void pmu_stop_clear_cycle_cntr(void)
{
pmu_stop_cycle_cntr();
arm_write_pmccntr(0);
}
/* Get cycle counter value. */
static inline uint32_t pmu_get_cycle_cntr(void)
{
return arm_read_pmccntr();
}
/* Bind event counter to specific event and start it. */
static inline void pmu_start_evt_cntr(pmu_evt_cntr_e cntr,
pmu_evt_e evt)
{
arm_write_pmselr(cntr);
arm_write_pmxevtyper(evt);
arm_write_pmcntenset(1 << cntr);
}
/* Stop event counter without clearing. */
static inline void pmu_stop_evt_cntr(pmu_evt_cntr_e cntr)
{
arm_write_pmcntenclr(1 << cntr);
}
/* Stop and clear the event counter. */
static inline void pmu_stop_clear_evt_cntr(pmu_evt_cntr_e cntr)
{
pmu_stop_evt_cntr(cntr);
arm_write_pmselr(cntr);
arm_write_pmxevcntr(0);
}
/* Get event counter value. */
static inline uint32_t pmu_get_evt_cntr(pmu_evt_cntr_e cntr)
{
arm_write_pmselr(cntr);
return arm_read_pmxevcntr();
}
#else
#define pmu_enable()
#define pmu_disable()
#define pmu_start_cycle_cntr(div64)
#define pmu_stop_cycle_cntr()
#define pmu_stop_clear_cycle_cntr()
#define pmu_get_cycle_cntr()
#define pmu_start_evt_cntr()
#define pmu_stop_evt_cntr()
#define pmu_stop_clear_evt_cntr()
#define pmu_get_evt_cntr()
#endif
#endif /* ARCH_ARM_PMU_H */

View File

@@ -0,0 +1,269 @@
/*
* register.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM cp register interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_REGISTER_H
#define INCLUDE_ARCH_REGISTER_H
#define REG_R0 (0)
#define REG_R1 (1)
#define REG_R2 (2)
#define REG_R3 (3)
#define REG_R4 (4)
#define REG_R5 (5)
#define REG_R6 (6)
#define REG_R7 (7)
#define REG_R8 (8)
#define REG_R9 (9)
#define REG_R10 (10)
#define REG_R11 (11)
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_CPSR (16)
#define ARM_CONTEXT_REGS (17)
/* If the MCU supports a floating point unit, then it will be necessary
* to save the state of the FPU status register and data registers on
* each context switch. These registers are not saved during interrupt
* level processing, however. So, as a consequence, floating point
* operations may NOT be performed in interrupt handlers.
*
* The FPU provides an extension register file containing 32 single-
* precision registers. These can be viewed as:
*
* - Sixteen 64-bit double word registers, D0-D15
* - Thirty-two 32-bit single-word registers, S0-S31
* S<2n> maps to the least significant half of D<n>
* S<2n+1> maps to the most significant half of D<n>.
*/
#if CONFIG_ARCH_WITH_FPU
# define REG_D0 (ARM_CONTEXT_REGS+0) /* D0 */
# define REG_S0 (ARM_CONTEXT_REGS+0) /* S0 */
# define REG_S1 (ARM_CONTEXT_REGS+1) /* S1 */
# define REG_D1 (ARM_CONTEXT_REGS+2) /* D1 */
# define REG_S2 (ARM_CONTEXT_REGS+2) /* S2 */
# define REG_S3 (ARM_CONTEXT_REGS+3) /* S3 */
# define REG_D2 (ARM_CONTEXT_REGS+4) /* D2 */
# define REG_S4 (ARM_CONTEXT_REGS+4) /* S4 */
# define REG_S5 (ARM_CONTEXT_REGS+5) /* S5 */
# define REG_D3 (ARM_CONTEXT_REGS+6) /* D3 */
# define REG_S6 (ARM_CONTEXT_REGS+6) /* S6 */
# define REG_S7 (ARM_CONTEXT_REGS+7) /* S7 */
# define REG_D4 (ARM_CONTEXT_REGS+8) /* D4 */
# define REG_S8 (ARM_CONTEXT_REGS+8) /* S8 */
# define REG_S9 (ARM_CONTEXT_REGS+9) /* S9 */
# define REG_D5 (ARM_CONTEXT_REGS+10) /* D5 */
# define REG_S10 (ARM_CONTEXT_REGS+10) /* S10 */
# define REG_S11 (ARM_CONTEXT_REGS+11) /* S11 */
# define REG_D6 (ARM_CONTEXT_REGS+12) /* D6 */
# define REG_S12 (ARM_CONTEXT_REGS+12) /* S12 */
# define REG_S13 (ARM_CONTEXT_REGS+13) /* S13 */
# define REG_D7 (ARM_CONTEXT_REGS+14) /* D7 */
# define REG_S14 (ARM_CONTEXT_REGS+14) /* S14 */
# define REG_S15 (ARM_CONTEXT_REGS+15) /* S15 */
# define REG_D8 (ARM_CONTEXT_REGS+16) /* D8 */
# define REG_S16 (ARM_CONTEXT_REGS+16) /* S16 */
# define REG_S17 (ARM_CONTEXT_REGS+17) /* S17 */
# define REG_D9 (ARM_CONTEXT_REGS+18) /* D9 */
# define REG_S18 (ARM_CONTEXT_REGS+18) /* S18 */
# define REG_S19 (ARM_CONTEXT_REGS+19) /* S19 */
# define REG_D10 (ARM_CONTEXT_REGS+20) /* D10 */
# define REG_S20 (ARM_CONTEXT_REGS+20) /* S20 */
# define REG_S21 (ARM_CONTEXT_REGS+21) /* S21 */
# define REG_D11 (ARM_CONTEXT_REGS+22) /* D11 */
# define REG_S22 (ARM_CONTEXT_REGS+22) /* S22 */
# define REG_S23 (ARM_CONTEXT_REGS+23) /* S23 */
# define REG_D12 (ARM_CONTEXT_REGS+24) /* D12 */
# define REG_S24 (ARM_CONTEXT_REGS+24) /* S24 */
# define REG_S25 (ARM_CONTEXT_REGS+25) /* S25 */
# define REG_D13 (ARM_CONTEXT_REGS+26) /* D13 */
# define REG_S26 (ARM_CONTEXT_REGS+26) /* S26 */
# define REG_S27 (ARM_CONTEXT_REGS+27) /* S27 */
# define REG_D14 (ARM_CONTEXT_REGS+28) /* D14 */
# define REG_S28 (ARM_CONTEXT_REGS+28) /* S28 */
# define REG_S29 (ARM_CONTEXT_REGS+29) /* S29 */
# define REG_D15 (ARM_CONTEXT_REGS+30) /* D15 */
# define REG_S30 (ARM_CONTEXT_REGS+30) /* S30 */
# define REG_S31 (ARM_CONTEXT_REGS+31) /* S31 */
# define REG_FPSCR (ARM_CONTEXT_REGS+32) /* Floating point status and control */
# define FPU_CONTEXT_REGS (33)
#else
# define FPU_CONTEXT_REGS (0)
#endif
/* The total number of registers saved by software */
#define XCPTCONTEXT_REGS (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
#ifndef ASSEMBLY
#include <types.h>
#include <compiler.h>
#include <armv7-r/barriers.h>
static inline uint32_t read_cpsr(void)
{
uint32_t cpsr;
__ASM volatile("mrs %0, cpsr" : "=r" (cpsr));
return cpsr;
}
#define ARM_CP_REG_FUNCS(cp, reg, op1, c1, c2, op2) \
static inline uint32_t arm_read_##reg(void) { \
uint32_t val; \
__ASM volatile("mrc " #cp ", " #op1 ", %0, " #c1 "," #c2 "," #op2 : "=r" (val)); \
return val; \
} \
\
static inline void arm_write_##reg(uint32_t val) { \
__ASM volatile("mcr " #cp ", " #op1 ", %0, " #c1 "," #c2 "," #op2 :: "r" (val)); \
ISB; \
}
#define ARM_CP15_REG_FUNCS(reg, op1, c1, c2, op2) \
ARM_CP_REG_FUNCS(p15, reg, op1, c1, c2, op2)
#define ARM_CP14_REG_FUNCS(reg, op1, c1, c2, op2) \
ARM_CP_REG_FUNCS(p14, reg, op1, c1, c2, op2)
#define ARM_CP10_REG_FUNCS(reg, op1, c1, c2, op2) \
ARM_CP_REG_FUNCS(p10, reg, op1, c1, c2, op2)
ARM_CP15_REG_FUNCS(sctlr, 0, c1, c0, 0);
ARM_CP15_REG_FUNCS(actlr, 0, c1, c0, 1);
ARM_CP15_REG_FUNCS(cpacr, 0, c1, c0, 2);
ARM_CP15_REG_FUNCS(ttbr, 0, c2, c0, 0);
ARM_CP15_REG_FUNCS(ttbr0, 0, c2, c0, 0);
ARM_CP15_REG_FUNCS(ttbr1, 0, c2, c0, 1);
ARM_CP15_REG_FUNCS(ttbcr, 0, c2, c0, 2);
ARM_CP15_REG_FUNCS(dacr, 0, c3, c0, 0);
ARM_CP15_REG_FUNCS(dfsr, 0, c5, c0, 0);
ARM_CP15_REG_FUNCS(ifsr, 0, c5, c0, 1);
ARM_CP15_REG_FUNCS(dfar, 0, c6, c0, 0);
ARM_CP15_REG_FUNCS(wfar, 0, c6, c0, 1);
ARM_CP15_REG_FUNCS(ifar, 0, c6, c0, 2);
ARM_CP15_REG_FUNCS(fcseidr, 0, c13, c0, 0);
ARM_CP15_REG_FUNCS(contextidr, 0, c13, c0, 1);
ARM_CP15_REG_FUNCS(tpidrurw, 0, c13, c0, 2);
ARM_CP15_REG_FUNCS(tpidruro, 0, c13, c0, 3);
ARM_CP15_REG_FUNCS(tpidrprw, 0, c13, c0, 4);
ARM_CP15_REG_FUNCS(midr, 0, c0, c0, 0);
ARM_CP15_REG_FUNCS(mpidr, 0, c0, c0, 5);
ARM_CP15_REG_FUNCS(vbar, 0, c12, c0, 0);
ARM_CP15_REG_FUNCS(cbar, 4, c15, c0, 0);
ARM_CP15_REG_FUNCS(ats1cpr, 0, c7, c8, 0);
ARM_CP15_REG_FUNCS(ats1cpw, 0, c7, c8, 1);
ARM_CP15_REG_FUNCS(ats1cur, 0, c7, c8, 2);
ARM_CP15_REG_FUNCS(ats1cuw, 0, c7, c8, 3);
ARM_CP15_REG_FUNCS(ats12nsopr, 0, c7, c8, 4);
ARM_CP15_REG_FUNCS(ats12nsopw, 0, c7, c8, 5);
ARM_CP15_REG_FUNCS(ats12nsour, 0, c7, c8, 6);
ARM_CP15_REG_FUNCS(ats12nsouw, 0, c7, c8, 7);
ARM_CP15_REG_FUNCS(par, 0, c7, c4, 0);
/* Branch predictor invalidate */
ARM_CP15_REG_FUNCS(bpiall, 0, c7, c5, 6);
ARM_CP15_REG_FUNCS(bpimva, 0, c7, c5, 7);
ARM_CP15_REG_FUNCS(bpiallis, 0, c7, c1, 6);
/* tlb registers */
ARM_CP15_REG_FUNCS(tlbiallis, 0, c8, c3, 0);
ARM_CP15_REG_FUNCS(tlbimvais, 0, c8, c3, 1);
ARM_CP15_REG_FUNCS(tlbiasidis, 0, c8, c3, 2);
ARM_CP15_REG_FUNCS(tlbimvaais, 0, c8, c3, 3);
ARM_CP15_REG_FUNCS(itlbiall, 0, c8, c5, 0);
ARM_CP15_REG_FUNCS(itlbimva, 0, c8, c5, 1);
ARM_CP15_REG_FUNCS(itlbiasid, 0, c8, c5, 2);
ARM_CP15_REG_FUNCS(dtlbiall, 0, c8, c6, 0);
ARM_CP15_REG_FUNCS(dtlbimva, 0, c8, c6, 1);
ARM_CP15_REG_FUNCS(dtlbiasid, 0, c8, c6, 2);
ARM_CP15_REG_FUNCS(tlbiall, 0, c8, c7, 0);
ARM_CP15_REG_FUNCS(tlbimva, 0, c8, c7, 1);
ARM_CP15_REG_FUNCS(tlbiasid, 0, c8, c7, 2);
ARM_CP15_REG_FUNCS(tlbimvaa, 0, c8, c7, 3);
ARM_CP15_REG_FUNCS(l2ctlr, 1, c9, c0, 2);
ARM_CP15_REG_FUNCS(l2ectlr, 1, c9, c0, 3);
/* mpu registers (using unified memory regions) */
ARM_CP15_REG_FUNCS(mpuir, 0, c0, c0, 4);
ARM_CP15_REG_FUNCS(rbar, 0, c6, c1, 0);
ARM_CP15_REG_FUNCS(rsr, 0, c6, c1, 2);
ARM_CP15_REG_FUNCS(racr, 0, c6, c1, 4);
ARM_CP15_REG_FUNCS(rgnr, 0, c6, c2, 0);
/* performance monitor registers */
ARM_CP15_REG_FUNCS(pmcr, 0, c9, c12, 0);
ARM_CP15_REG_FUNCS(pmcntenset, 0, c9, c12, 1);
ARM_CP15_REG_FUNCS(pmcntenclr, 0, c9, c12, 2);
ARM_CP15_REG_FUNCS(pmovsr, 0, c9, c12, 3);
ARM_CP15_REG_FUNCS(pmswinc, 0, c9, c12, 4);
ARM_CP15_REG_FUNCS(pmselr, 0, c9, c12, 5);
ARM_CP15_REG_FUNCS(pmccntr, 0, c9, c13, 0);
ARM_CP15_REG_FUNCS(pmxevtyper, 0, c9, c13, 1);
ARM_CP15_REG_FUNCS(pmxevcntr, 0, c9, c13, 2);
/* TCM registers */
ARM_CP15_REG_FUNCS(tcmtr, 0, c0, c0, 2);
ARM_CP15_REG_FUNCS(btcmrgn, 0, c9, c1, 0);
ARM_CP15_REG_FUNCS(atcmrgn, 0, c9, c1, 1);
/* debug registers */
ARM_CP14_REG_FUNCS(dbddidr, 0, c0, c0, 0);
ARM_CP14_REG_FUNCS(dbgdrar, 0, c1, c0, 0);
ARM_CP14_REG_FUNCS(dbgdsar, 0, c2, c0, 0);
ARM_CP14_REG_FUNCS(dbgdscr, 0, c0, c1, 0);
ARM_CP14_REG_FUNCS(dbgdtrtxint, 0, c0, c5, 0);
ARM_CP14_REG_FUNCS(dbgdtrrxint, 0, c0, c5, 0);
ARM_CP14_REG_FUNCS(dbgwfar, 0, c0, c6, 0);
ARM_CP14_REG_FUNCS(dbgvcr, 0, c0, c7, 0);
ARM_CP14_REG_FUNCS(dbgecr, 0, c0, c9, 0);
ARM_CP14_REG_FUNCS(dbgdsccr, 0, c0, c10, 0);
ARM_CP14_REG_FUNCS(dbgdsmcr, 0, c0, c11, 0);
ARM_CP14_REG_FUNCS(dbgdtrrxext, 0, c0, c0, 2);
ARM_CP14_REG_FUNCS(dbgdscrext, 0, c0, c2, 2);
ARM_CP14_REG_FUNCS(dbgdtrtxext, 0, c0, c3, 2);
ARM_CP14_REG_FUNCS(dbgdrcr, 0, c0, c4, 2);
ARM_CP14_REG_FUNCS(dbgvr0, 0, c0, c0, 4);
ARM_CP14_REG_FUNCS(dbgvr1, 0, c0, c1, 4);
ARM_CP14_REG_FUNCS(dbgvr2, 0, c0, c2, 4);
ARM_CP14_REG_FUNCS(dbgbcr0, 0, c0, c0, 5);
ARM_CP14_REG_FUNCS(dbgbcr1, 0, c0, c1, 5);
ARM_CP14_REG_FUNCS(dbgbcr2, 0, c0, c2, 5);
ARM_CP14_REG_FUNCS(dbgwvr0, 0, c0, c0, 6);
ARM_CP14_REG_FUNCS(dbgwvr1, 0, c0, c1, 6);
ARM_CP14_REG_FUNCS(dbgwcr0, 0, c0, c0, 7);
ARM_CP14_REG_FUNCS(dbgwcr1, 0, c0, c1, 7);
ARM_CP14_REG_FUNCS(dbgoslar, 0, c1, c0, 4);
ARM_CP14_REG_FUNCS(dbgoslsr, 0, c1, c1, 4);
ARM_CP14_REG_FUNCS(dbgossrr, 0, c1, c2, 4);
ARM_CP14_REG_FUNCS(dbgprcr, 0, c1, c4, 4);
ARM_CP14_REG_FUNCS(dbgprsr, 0, c1, c5, 4);
ARM_CP14_REG_FUNCS(dbgclaimset, 0, c7, c8, 6);
ARM_CP14_REG_FUNCS(dbgclaimclr, 0, c7, c9, 6);
ARM_CP14_REG_FUNCS(dbgauthstatus, 0, c7, c14, 6);
ARM_CP14_REG_FUNCS(dbgdevid, 0, c7, c2, 7);
/* fpu registers */
ARM_CP10_REG_FUNCS(fpexc, 7, c8, c0, 0);
#endif /* ASSEMBLY */
#endif /* INCLUDE_ARCH_REGISTER_H */

View File

@@ -0,0 +1,118 @@
/*
* spinlock.h
*
* Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*
* Description: ARM spinlock interface.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARM_SPINLOCK_H
#define INCLUDE_ARM_SPINLOCK_H
#include <armv7-r/barriers.h>
#define SPIN_LOCK_INITIAL_VALUE (0)
#ifndef ASSEMBLY
__BEGIN_CDECLS
/* spin lock type */
typedef unsigned long spin_lock_t;
#ifdef CONFIG_MULTI_CORE_SMP
#else
static inline int __arch_spin_lock_testset(spin_lock_t *spinlock, int value)
{
int result = 0;
__ASM volatile
(
"1:\n"
"\tldrex %0, [%1]\n"
"\tcmp %0, %2\n"
"\tbeq 2f\n"
"\tstrex %0, %2, [%1]\n"
"\tcmp %0, %2\n"
"\tbeq 1b\n"
"\tdmb ish\n"
"2:\n"
: "=&r" (result)
: "r" (spinlock), "r" (value)
: "cc", "memory"
);
return result;
}
#endif
/*
* arch spinlock init.
*
* @spinlock spinlock address.
*/
#ifdef CONFIG_MULTI_CORE_SMP
void arch_spin_lock_init(spin_lock_t *spinlock);
#else
static inline void arch_spin_lock_init(spin_lock_t *spinlock)
{
*spinlock = SPIN_LOCK_INITIAL_VALUE;
}
#endif
/*
* arch spin lock.
*
* @spinlock spinlock address.
*/
#ifdef CONFIG_MULTI_CORE_SMP
void arch_spin_lock(spin_lock_t *spinlock);
#else
static inline void arch_spin_lock(spin_lock_t *spinlock)
{
/* spin until lock is acquired */
while (__arch_spin_lock_testset(spinlock, 1)) {
DSB;
};
}
#endif
/*
* arch spin trylock.
*
* @spinlock spinlock address.
*/
#ifdef CONFIG_MULTI_CORE_SMP
int arch_spin_trylock(spin_lock_t *spinlock);
#else
static inline int arch_spin_trylock(spin_lock_t *spinlock)
{
return __arch_spin_lock_testset(spinlock, 1) == 0;
}
#endif
/*
* arch spin unlock.
*
* @spinlock spinlock address.
*/
#ifdef CONFIG_MULTI_CORE_SMP
void arch_spin_unlock(spin_lock_t *spinlock);
#else
static inline void arch_spin_unlock(spin_lock_t *spinlock)
{
DMB;
*spinlock = 0;
DSB;
}
#endif
__END_CDECLS
#endif
#endif

View File

@@ -0,0 +1,39 @@
/*
* svcall.h
*
* Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*
* Description: SV call header file.
*
* Revision History:
* -----------------
*/
#ifndef ARM_V7R_SVCALL_H_
#define ARM_V7R_SVCALL_H_
/* Cortex-R system calls ************************************************************/
/* SYS call 0:
*
* int arm_saveusercontext(uint32_t *saveregs);
*/
#define SYS_save_context (0)
/* SYS call 1:
*
* void arm_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
*/
#define SYS_restore_context (1)
/* SYS call 2:
*
* void arm_switchcontext(void);
*/
#define SYS_switch_context (2)
#endif /* ARM_V7R_SVCALL_H_ */

View File

@@ -0,0 +1,55 @@
/*
* tcm.h
*
* Copyright (c) 2019 Semidrive Semiconductor.
* All rights reserved.
*
* Description: Cortex V7R TCM driver.
*
* Revision History:
* -----------------
*/
#ifndef INCLUDE_ARCH_ARMV7R_TCM_H
#define INCLUDE_ARCH_ARMV7R_TCM_H
#define ATCMPCEN (1ul << 25)
#define B0TCMPCEN (1ul << 26)
#define B1TCMPCEN (1ul << 27)
#ifndef ASSEMBLY
#include <types.h>
#include <compiler.h>
#include <stdbool.h>
__BEGIN_CDECLS
/*
* tcma enable.
*
* @atcm_base tcma base address.
* @enable_ecc enable tcm ecc.
*/
#if CONFIG_ARM_WITH_TCM
void tcma_enable(uint32_t tcm_base, bool enable_ecc);
#else
#define tcma_enable(tcm_base, enable_ecc)
#endif
/*
* tcmb enable.
*
* @atcm_base tcmb base address.
* @enable_ecc enable tcm ecc.
*/
#if CONFIG_ARM_WITH_TCM
void tcmb_enable(uint32_t tcm_base, bool enable_ecc);
#else
#define tcmb_enable(tcm_base, enable_ecc)
#endif
__END_CDECLS
#endif
#endif