Skip to content

Commit

Permalink
Cortex-M: NVIC and SCB code duplication cleanup
Browse files Browse the repository at this point in the history
JIRA: RTOS-886
  • Loading branch information
agkaminski committed Aug 9, 2024
1 parent fa2cb46 commit ef753d4
Show file tree
Hide file tree
Showing 42 changed files with 509 additions and 1,214 deletions.
10 changes: 10 additions & 0 deletions hal/arm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# Makefile for HAL ARM common functions
#
# Copyright 2023 Phoenix Systems
#

# TODO handle other common ARM stuff (e.g GIC) and
# select relevant components here

OBJS += $(addprefix $(PREFIX_O)hal/arm/, nvic.o scb.o)
7 changes: 4 additions & 3 deletions hal/armv7m/armv7m.h → hal/arm/barriers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Operating system kernel
*
* ARMv7 Cortex-M related routines
* ARM barriers
*
* Copyright 2021 Phoenix Systems
* Author: Hubert Buczynski
Expand All @@ -13,8 +13,8 @@
* %LICENSE%
*/

#ifndef _HAL_ARMV7M_H_
#define _HAL_ARMV7M_H_
#ifndef HAL_ARM_BARRIERS_H_
#define HAL_ARM_BARRIERS_H_


static inline void hal_cpuDataMemoryBarrier(void)
Expand All @@ -34,4 +34,5 @@ static inline void hal_cpuInstrBarrier(void)
__asm__ volatile ("isb");
}


#endif
66 changes: 66 additions & 0 deletions hal/arm/nvic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Phoenix-RTOS
*
* Operating system kernel
*
* Nested Vector Interrupt Controller
*
* Copyright 2017, 2020, 2022, 2024 Phoenix Systems
* Author: Pawel Pisarczyk, Hubert Buczynski, Damian Loewnau, Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/


#include <arch/cpu.h>
#include "nvic.h"


static struct {
volatile u32 *nvic;
} nvic_common;


/* clang-format off */
enum { nvic_iser = 0, nvic_icer = 32, nvic_ispr = 64, nvic_icpr = 96, nvic_iabr = 128,
nvic_ip = 192 };
/* clang-format on */


void _hal_nvicSetIRQ(s8 irqn, u8 state)
{
volatile u32 *ptr = nvic_common.nvic + ((u8)irqn >> 5) + ((state != 0) ? nvic_iser : nvic_icer);
*ptr = 1u << (irqn & 0x1f);

hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}


void _hal_nvicSetPriority(s8 irqn, u32 priority)
{
volatile u32 *ptr;

ptr = ((u32 *)(nvic_common.nvic + nvic_ip)) + (irqn / 4);

/* We set only group priority field */
*ptr = (priority << (8 * (irqn % 4) + 4));
}


void _hal_nvicSetPending(s8 irqn)
{
volatile u32 *ptr = nvic_common.nvic + ((u8)irqn >> 5) + nvic_ispr;

*ptr = 1u << (irqn & 0x1f);

hal_cpuDataSyncBarrier();
}


void _hal_nvicInit(void)
{
nvic_common.nvic = (void *)0xe000e100;
}
36 changes: 36 additions & 0 deletions hal/arm/nvic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Phoenix-RTOS
*
* Operating system kernel
*
* Nested Vector Interrupt Controller
*
* Copyright 2017, 2020, 2022, 2024 Phoenix Systems
* Author: Pawel Pisarczyk, Hubert Buczynski, Damian Loewnau, Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/


#ifndef HAL_ARMV_NVIC_H_
#define HAL_ARMV_NVIC_H_


#include "hal/types.h"


void _hal_nvicSetIRQ(s8 irqn, u8 state);


void _hal_nvicSetPriority(s8 irqn, u32 priority);


void _hal_nvicSetPending(s8 irqn);


void _hal_nvicInit(void);


#endif
244 changes: 244 additions & 0 deletions hal/arm/scb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* Phoenix-RTOS
*
* Operating system kernel
*
* System Control Block
*
* Copyright 2017, 2020, 2022, 2024 Phoenix Systems
* Author: Pawel Pisarczyk, Hubert Buczynski, Gerard Swiderski, Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/


#include <arch/cpu.h>
#include "scb.h"


static struct {
volatile u32 *scb;
volatile u32 *systick;
} scb_common;


/* clang-format off */
enum { scb_cpuid = 0, scb_icsr, scb_vtor, scb_aircr, scb_scr, scb_ccr, scb_shp0, scb_shp1,
scb_shp2, scb_shcsr, scb_cfsr, scb_hfsr, scb_dfsr, scb_mmfar, scb_bfar, scb_afsr, scb_pfr0,
scb_pfr1, scb_dfr, scb_afr, scb_mmfr0, scb_mmfr1, scb_mmfr2, scb_mmf3, scb_isar0, scb_isar1,
scb_isar2, scb_isar3, scb_isar4, /* reserved */ scb_clidr = 30, scb_ctr, scb_ccsidr, scb_csselr,
scb_cpacr, /* 93 reserved */ scb_stir = 128, /* 12 reserved */ scb_fpccr = 141, /* 2 reserved*/
scb_mvfr0 = 144, scb_mvfr1, scb_mvfr2, /* reserved */ scb_iciallu = 148, /* reserved */
scb_icimvau = 150, scb_scimvac, scb_dcisw, scb_dccmvau, scb_dccmvac, scb_dccsw, scb_dccimvac,
scb_dccisw, /* 6 reserved */ scb_itcmcr = 164, scb_dtcmcr, scb_ahbpcr, scb_cacr, scb_ahbscr,
/* reserved */ scb_abfsr = 170
};


enum { syst_csr = 4, syst_rvr, syst_cvr, syst_calib };
/* clang-format on */


void _hal_scbSetPriorityGrouping(u32 group)
{
u32 t;

/* Get register value and clear bits to set */
t = *(scb_common.scb + scb_aircr) & ~0xffff0700;

/* Set AIRCR.PRIGROUP to 3: 16 priority groups and 16 subgroups
The value is same as for armv7m4-stm32l4x6 target
Setting various priorities is not supported on Phoenix-RTOS, so it's just default value */
*(scb_common.scb + scb_aircr) = t | 0x5fa0000 | ((group & 7) << 8);
}


void _hal_scbSetPriority(s8 excpn, u32 priority)
{
volatile u8 *ptr;

ptr = &((u8 *)(scb_common.scb + scb_shp1))[excpn - 4];

/* We set only group priority field */
*ptr = (priority << 4) & 0xff;
}


void _hal_scbSystemReset(void)
{
*(scb_common.scb + scb_aircr) = ((0x5fau << 16) | (*(scb_common.scb + scb_aircr) & (0x700u)) | (1u << 2));

hal_cpuDataSyncBarrier();

for (;;) {
hal_cpuHalt();
}
}


unsigned int _hal_scbCpuid(void)
{
return *(scb_common.scb + scb_cpuid);
}


void _hal_scbSetFPU(int state)
{
if (state != 0) {
*(scb_common.scb + scb_cpacr) |= 0xf << 20;

/* Enable FPU ctx */
/* TODO remove this and make sure correct control
* is set after that (first process) */
__asm__ volatile (
"mrs r0, control\n\t"
"orr r0, r0, #(1 << 2)\n\t"
"msr control, r0\n\t"
"isb"
);
}
else {
*(scb_common.scb + scb_cpacr) = 0;
*(scb_common.scb + scb_fpccr) = 0;
}
hal_cpuDataSyncBarrier();
}


void _hal_scbEnableDCache(void)
{
u32 ccsidr, sets, ways;

if ((*(scb_common.scb + scb_ccr) & (1 << 16)) == 0) {
*(scb_common.scb + scb_csselr) = 0;
hal_cpuDataSyncBarrier();

ccsidr = *(scb_common.scb + scb_ccsidr);

/* Invalidate D$ */
sets = (ccsidr >> 13) & 0x7fff;
do {
ways = (ccsidr >> 3) & 0x3ff;
do {
*(scb_common.scb + scb_dcisw) = ((sets & 0x1ff) << 5) | ((ways & 0x3) << 30);
} while (ways-- != 0);
} while (sets-- != 0);
hal_cpuDataSyncBarrier();

*(scb_common.scb + scb_ccr) |= 1 << 16;

hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}
}


void _hal_scbDisableDCache(void)
{
register u32 ccsidr, sets, ways;

*(scb_common.scb + scb_csselr) = 0;
hal_cpuDataSyncBarrier();

*(scb_common.scb + scb_ccr) &= ~(1 << 16);
hal_cpuDataSyncBarrier();

ccsidr = *(scb_common.scb + scb_ccsidr);

sets = (ccsidr >> 13) & 0x7fff;
do {
ways = (ccsidr >> 3) & 0x3ff;
do {
*(scb_common.scb + scb_dcisw) = ((sets & 0x1ff) << 5) | ((ways & 0x3) << 30);
} while (ways-- != 0);
} while (sets-- != 0);

hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}


void _hal_scbCleanInvalDCacheAddr(void *addr, u32 sz)
{
u32 daddr;
int dsize;

if (sz == 0u) {
return;
}

daddr = (((u32)addr) & ~0x1fu);
dsize = sz + ((u32)addr & 0x1fu);

hal_cpuDataSyncBarrier();

do {
*(scb_common.scb + scb_dccimvac) = daddr;
daddr += 0x20u;
dsize -= 0x20;
} while (dsize > 0);

hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}


void _hal_scbEnableICache(void)
{
if ((*(scb_common.scb + scb_ccr) & (1 << 17)) == 0) {
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
*(scb_common.scb + scb_iciallu) = 0; /* Invalidate I$ */
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
*(scb_common.scb + scb_ccr) |= 1 << 17;
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}
}


void _hal_scbDisableICache(void)
{
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
*(scb_common.scb + scb_ccr) &= ~(1 << 17);
*(scb_common.scb + scb_iciallu) = 0;
hal_cpuDataSyncBarrier();
hal_cpuInstrBarrier();
}


void _hal_scbSetDeepSleep(int state)
{
if (state != 0) {
*(scb_common.scb + scb_scr) &= ~(1 << 2);
*(scb_common.systick + syst_csr) &= ~1;
}
else {
*(scb_common.scb + scb_scr) |= 1 << 2;
*(scb_common.systick + syst_csr) |= 1;
}
}


void _hal_scbSystickInit(u32 load)
{
*(scb_common.systick + syst_rvr) = (u32)load;
*(scb_common.systick + syst_cvr) = 0;

/* Enable systick */
*(scb_common.systick + syst_csr) |= 0x7;
}


void _hal_scbInit(void)
{
scb_common.scb = (void *)0xe000ed00;
scb_common.systick = (void *)0xe000e000;

/* Enable UsageFault, BusFault and MemManage exceptions */
*(scb_common.scb + scb_shcsr) |= (1u << 16) | (1u << 17) | (1u << 18);
}
Loading

0 comments on commit ef753d4

Please sign in to comment.