pull/1/head
Felix Kopp 4 years ago
parent 2ca4706e39
commit 30096ab5b2
No known key found for this signature in database
GPG Key ID: C478BA0A85F75728

@ -37,7 +37,7 @@ CFLAGS = $(EXTRA_CFLAGS)
CFLAGS += -g -nodefaultlibs -nostartfiles
CFLAGS += -I$(PWD)/include
CFLAGS += -DARCH=$(ARCH)
CFLAGS += -fpack-struct -fno-builtin -std=gnu11
CFLAGS += -fno-builtin -std=gnu11
EXTRA_LDFLAGS ?=
LDFLAGS = $(EXTRA_LDFLAGS)

@ -26,8 +26,7 @@
ARDIX_ARCH_PWD = $(PWD)/arch/at91sam3x8e
ARDIX_SOURCES += \
$(ARDIX_ARCH_PWD)/isr_sched.c \
$(ARDIX_ARCH_PWD)/sched_hwtimer.c \
$(ARDIX_ARCH_PWD)/sched.c \
$(ARDIX_ARCH_PWD)/startup.c
ARDIX_ASM_SOURCES += \

@ -25,22 +25,51 @@
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch/sched.h>
#include <arch/at91sam3x8e/hardware.h>
#include <arch/at91sam3x8e/interrupt.h>
#include <ardix/string.h>
#include <ardix/sched.h>
#include <stdbool.h>
#include <toolchain.h>
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif /* __cplusplus */
static __always_inline void sched_pendsv_req(void)
{
SCB_ICSR |= SCB_PENDSVSET_MASK;
}
void isr_sys_tick(void)
{
/*
* fire a PendSV interrupt and do the actual context switching there
* because it is faster that way (according to the docs, at least)
*/
SCB_ICSR |= SCB_PENDSVSET_MASK;
sched_pendsv_req();
}
int sched_hwtimer_init(unsigned int freq)
{
uint32_t ticks = F_CPU / freq;
if (ticks > REG_SYSTICK_LOAD_RELOAD_MASK)
return 1;
REG_SYSTICK_LOAD = (ticks & REG_SYSTICK_LOAD_RELOAD_MASK) - 1;
REG_SYSTICK_VAL = 0U;
REG_SYSTICK_CTRL = REG_SYSTICK_CTRL_CLKSOURCE_BIT /* MCK */
| REG_SYSTICK_CTRL_TICKINT_BIT /* trigger exception */
| REG_SYSTICK_CTRL_ENABLE_BIT; /* enable SysTick */
return 0;
}
{
}
{
}
#ifdef __cplusplus

@ -1,54 +0,0 @@
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2020 Felix Kopp <sandtler@sandtler.club>
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch/sched.h>
#include <arch/at91sam3x8e/hardware.h>
int sched_hwtimer_init(unsigned int freq)
{
uint32_t ticks = F_CPU / freq;
if (ticks > REG_SYSTICK_LOAD_RELOAD_MASK)
return 1;
REG_SYSTICK_LOAD = (ticks & REG_SYSTICK_LOAD_RELOAD_MASK) - 1;
REG_SYSTICK_VAL = 0U;
REG_SYSTICK_CTRL = REG_SYSTICK_CTRL_CLKSOURCE_MASK
| REG_SYSTICK_CTRL_TICKINT_MASK
| REG_SYSTICK_CTRL_ENABLE_MASK;
return 0;
}
void sched_hwtimer_pause(void)
{
REG_SYSTICK_CTRL &= ~REG_SYSTICK_CTRL_ENABLE_MASK;
}
void sched_hwtimer_resume(void)
{
REG_SYSTICK_CTRL |= REG_SYSTICK_CTRL_ENABLE_MASK;
}

@ -29,7 +29,6 @@
#include <stdint.h>
#include <arch/at91sam3x8e/interrupt.h>
#include <ardix/string.h>
#include <arch/at91sam3x8e/hardware.h>
#include <toolchain.h>
/* from flash.ld */
@ -46,88 +45,6 @@ extern uint32_t _estack; /* stack end */
/* implementation in init/main.c */
void do_bootstrap(void);
/**
* Keep the CPU busy by continuously checking the same
* expression over and over again until it is true.
*
* @param expr The expression.
*/
#define mom_are_we_there_yet(expr) while (!(expr))
/** Prepare the system for bootstrapping the Kernel. */
void sys_init(void)
{
/*
* This method is basically an implementation of chapter 28.12 in the
* Atmel SAM3X8E Datasheet, combined with the startup code from libsam.
*/
/* # of wait states as per hardware spec (stolen from SAM SysInit) */
REG_EEFC0_FMR = REG_EEFC_FWS_VAL(4);
REG_EEFC1_FMR = REG_EEFC_FWS_VAL(4);
/* disable osc write protection */
REG_PMC_WPMR = REG_PMC_WPMR_WPKEY_VAL(REG_PMC_WPMR_WPKEY_MAGIC)
& ~REG_PMC_WPMR_WPEN_BIT;
/*
* 1. Enabling the Main Oscillator
*/
/* initialize main osc */
if (!(REG_CKGR_MOR & REG_CKGR_MOR_MOSCSEL_BIT)) {
REG_CKGR_MOR = REG_CKGR_MOR_KEY_VAL(REG_CKGR_MOR_KEY_MAGIC)
| REG_CKGR_MOR_MOSCXTST_VAL(8)
| REG_CKGR_MOR_MOSCRCEN_BIT
| REG_CKGR_MOR_MOSCXTEN_BIT;
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MOSCXTS_BIT);
}
/* switch to Xtal osc */
REG_CKGR_MOR = REG_CKGR_MOR_KEY_VAL(REG_CKGR_MOR_KEY_MAGIC)
| REG_CKGR_MOR_MOSCXTST_VAL(8)
| REG_CKGR_MOR_MOSCRCEN_BIT
| REG_CKGR_MOR_MOSCXTEN_BIT
| REG_CKGR_MOR_MOSCSEL_BIT;
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MOSCXTS_BIT);
REG_PMC_MCKR = (REG_PMC_MCKR & ~REG_PMC_MCKR_CSS_MASK)
| REG_PMC_MCKR_CSS_VAL(1 /* = main clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/*
* 2. Checking the Main Oscillator Frequency (Optional)
*/
/* I repeat: **(Optional)** */
/*
* 3. Setting PLL and Divider
*/
REG_CKGR_PLLAR = REG_CKGR_PLLAR_ONE_BIT
| REG_CKGR_PLLAR_MULA_VAL(0xD)
| REG_CKGR_PLLAR_PLLACOUNT_VAL(0x3F /* maximum value */)
| REG_CKGR_PLLAR_DIVA_VAL(0x1);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_LOCKA_BIT);
/*
* 4. Selection of Master Clock and Processor Clock
*/
REG_PMC_MCKR = REG_PMC_MCKR_PRES_VAL(1 /* = as fast as it gets */)
| REG_PMC_MCKR_CSS_VAL(1 /* = main clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/* PMC_MCKR must not be configured within one clock cycle */
REG_PMC_MCKR = REG_PMC_MCKR_PRES_VAL(1 /* = as fast as it gets */)
| REG_PMC_MCKR_CSS_VAL(2 /* = PLLA clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/* turn osc write protection on again */
REG_PMC_WPMR |= REG_PMC_WPMR_WPEN_BIT;
}
void isr_reset(void)
{
memmove(
@ -141,8 +58,6 @@ void isr_reset(void)
(size_t)(&_ezero) - (size_t)(&_szero)
);
sys_init();
/* start the Kernel */
do_bootstrap();

@ -0,0 +1,108 @@
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2020 Felix Kopp <sandtler@sandtler.club>
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
#include <stdint.h>
#include <arch/at91sam3x8e/interrupt.h>
#include <arch/hardware.h>
#include <ardix/string.h>
#include <toolchain.h>
int sys_init(void)
{
/*
* This method is basically an implementation of chapter 28.12 in the
* Atmel SAM3X8E Datasheet, combined with the startup code from libsam.
*/
/* # of wait states as per hardware spec (stolen from SAM SysInit) */
REG_EEFC0_FMR = REG_EEFC_FWS_VAL(4);
REG_EEFC1_FMR = REG_EEFC_FWS_VAL(4);
/* disable osc write protection */
REG_PMC_WPMR = REG_PMC_WPMR_WPKEY_VAL(REG_PMC_WPMR_WPKEY_MAGIC)
& ~REG_PMC_WPMR_WPEN_BIT;
/*
* 1. Enabling the Main Oscillator
*/
/* initialize main osc */
if (!(REG_CKGR_MOR & REG_CKGR_MOR_MOSCSEL_BIT)) {
REG_CKGR_MOR = REG_CKGR_MOR_KEY_VAL(REG_CKGR_MOR_KEY_MAGIC)
| REG_CKGR_MOR_MOSCXTST_VAL(8)
| REG_CKGR_MOR_MOSCRCEN_BIT
| REG_CKGR_MOR_MOSCXTEN_BIT;
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MOSCXTS_BIT);
}
/* switch to Xtal osc */
REG_CKGR_MOR = REG_CKGR_MOR_KEY_VAL(REG_CKGR_MOR_KEY_MAGIC)
| REG_CKGR_MOR_MOSCXTST_VAL(8)
| REG_CKGR_MOR_MOSCRCEN_BIT
| REG_CKGR_MOR_MOSCXTEN_BIT
| REG_CKGR_MOR_MOSCSEL_BIT;
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MOSCXTS_BIT);
REG_PMC_MCKR = (REG_PMC_MCKR & ~REG_PMC_MCKR_CSS_MASK)
| REG_PMC_MCKR_CSS_VAL(1 /* = main clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/*
* 2. Checking the Main Oscillator Frequency (Optional)
*/
/* I repeat: **(Optional)** */
/*
* 3. Setting PLL and Divider
*/
REG_CKGR_PLLAR = REG_CKGR_PLLAR_ONE_BIT
| REG_CKGR_PLLAR_MULA_VAL(0xD)
| REG_CKGR_PLLAR_PLLACOUNT_VAL(0x3F /* maximum value */)
| REG_CKGR_PLLAR_DIVA_VAL(0x1);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_LOCKA_BIT);
/*
* 4. Selection of Master Clock and Processor Clock
*/
REG_PMC_MCKR = REG_PMC_MCKR_PRES_VAL(1 /* = as fast as it gets */)
| REG_PMC_MCKR_CSS_VAL(1 /* = main clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/* PMC_MCKR must not be configured within one clock cycle */
REG_PMC_MCKR = REG_PMC_MCKR_PRES_VAL(1 /* = as fast as it gets */)
| REG_PMC_MCKR_CSS_VAL(2 /* = PLLA clock */);
mom_are_we_there_yet(REG_PMC_SR & REG_PMC_SR_MCKRDY_BIT);
/* turn osc write protection on again */
REG_PMC_WPMR |= REG_PMC_WPMR_WPEN_BIT;
return 0;
}

@ -83,30 +83,30 @@ struct reg_snapshot {
/** Real-time Timer Mode Register */
#define REG_RTT_MR (*(uint32_t *)0x400E1A30U)
/** Real-time Timer Restart bitmask (for `RTT_MR`) */
#define REG_RTTRST_MASK ((uint32_t)1 << 18)
#define REG_RTT_RTTRST_BIT ((uint32_t)1 << 18)
/** Real-time Timer Increment Interrupt Enable bitmask (for `REG_RTT_MR`) */
#define REG_RTTINCIEN_MASK ((uint32_t)1 << 17)
#define REG_RTT_RTTINCIEN_BIT ((uint32_t)1 << 17)
/** Alarm Interrupt Enable bitmask (for `REG_RTT_MR`) */
#define REG_ALMIEN_MASK ((uint32_t)1 << 16)
#define REG_RTT_ALMIEN_BIT ((uint32_t)1 << 16)
/** Real-time Timer Prescaler Value */
#define REG_RTPRES (*(uint16_t *)0x400E1A30U)
#define REG_RTT_RTPRES (*(uint16_t *)0x400E1A30U)
/** Real-time Timer Alarm Register */
#define REG_RTT_AR (*(uint32_t *)0x400E1A34U)
/** Real-time Timer Alarm Value */
#define REG_ALMV REG_RTT_AR
#define REG_RTT_AR_ALMV REG_RTT_AR
/** Real-time timer Value Register */
#define REG_RTT_VR (*(uint32_t *)0x400E1A38U)
/** Current Real-time Value */
#define REG_CRTV REG_RTT_VR
#define REG_RTT_VR_CRTV REG_RTT_VR
/** Real-time Timer Status Register */
#define REG_RTT_SR (*(const uint32_t *)0x400E1A3CU)
/** Real-time Timer Increment bitmask (for `REG_RTT_SR`) */
#define REG_RTTINC_MASK ((uint32_t)1 << 1)
#define REG_RTT_SR_RTTINC_BIT ((uint32_t)1 << 1)
/** Real-time Timer Alarm Status bitmask (for `REG_RTT_SR`) */
#define REG_ALMS_MASK ((uint32_t)1)
#define REG_RTT_SR_ALMS_BIT ((uint32_t)1)
/*
* SysTick
@ -115,13 +115,13 @@ struct reg_snapshot {
/** SysTick Control and Status Register */
#define REG_SYSTICK_CTRL (*(uint32_t *)0xE000E010U)
/** SysTick CTRL COUNTFLAG bitmask (for `REG_SYSTICK_CTRL`) */
#define REG_SYSTICK_CTRL_COUNTFLAG_MASK ((uint32_t)1 << 16)
#define REG_SYSTICK_CTRL_COUNTFLAG_BIT ((uint32_t)1 << 16)
/** SysTick CTRL CLKSOURCE bitmask (for `REG_SYSTICK_CTRL`) */
#define REG_SYSTICK_CTRL_CLKSOURCE_MASK ((uint32_t)1 << 2)
#define REG_SYSTICK_CTRL_CLKSOURCE_BIT ((uint32_t)1 << 2)
/** SysTick CTRL exception request enable bitmask (for `REG_SYSTICK_CTRL`) */
#define REG_SYSTICK_CTRL_TICKINT_MASK ((uint32_t)1 << 1)
#define REG_SYSTICK_CTRL_TICKINT_BIT ((uint32_t)1 << 1)
/** SysTick CTRL enable bitmask (for `REG_SYSTICK_CTRL`) */
#define REG_SYSTICK_CTRL_ENABLE_MASK ((uint32_t)1)
#define REG_SYSTICK_CTRL_ENABLE_BIT ((uint32_t)1)
/** SysTick Reload Value Register */
#define REG_SYSTICK_LOAD (*(uint32_t *)0xE000E014U)
@ -195,6 +195,22 @@ struct reg_snapshot {
/** ICSR active exception number bitmask (for `SCB_ICSR`) */
#define SCB_VECTACTIVE_MASK ((uint32_t)0b111111111u)
/*
* Enhanced Embedded Flash Controller (EEFC)
*/
/** EEFC 0 Flash Mode Register */
#define REG_EEFC0_FMR (*(uint32_t *)0x400E0A00U)
/** EEFC 1 Flash Mode Register */
#define REG_EEFC1_FMR (*(uint32_t *)0x400E0C00U)
/** EEFC Flash Access Mode bitmask */
#define REG_EEFC_FAM_BIT ((uint32_t)1 << 24)
/** EEFC Flash Wait State bitmask (number of cycles for read/write = FWS + 1) */
#define REG_EEFC_FWS_MASK ((uint32_t)0x7U << 8)
#define REG_EEFC_FWS_VAL(x) ( ((uint32_t)(x) << 8) & REG_EEFC_FWS_MASK )
/** EEFC Ready Interrupt Enable bitmask */
#define REG_EEFC_FRDY_BIT ((uint32_t)1)
/*
* Power Management Controller (PMC)
*/
@ -202,35 +218,35 @@ struct reg_snapshot {
/** PMC System Clock Enable Register */
#define REG_PMC_SCER (*(uint32_t *)0x400E0600U)
/** PMC Programmable Clock 2 Output Enable bitmask (for `REG_PMC_SCER`) */
#define REG_PMC_SCER_PCK2_MASK ((uint32_t)1 << 10)
#define REG_PMC_SCER_PCK2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock 1 Output Enable bitmask (for `REG_PMC_SCER`) */
#define REG_PMC_SCER_PCK1_MASK ((uint32_t)1 << 9)
#define REG_PMC_SCER_PCK1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock 0 Output Enable bitmask (for `REG_PMC_SCER`) */
#define REG_PMC_SCER_PCK0_MASK ((uint32_t)1 << 8)
#define REG_PMC_SCER_PCK0_BIT ((uint32_t)1 << 8)
/** PMC Enable USB OTG Clock bitmask for UTMI (for `REG_PMC_SCER`) */
#define REG_PMC_SCER_UOTGCLK_MASK ((uint32_t)1 << 5)
#define REG_PMC_SCER_UOTGCLK_BIT ((uint32_t)1 << 5)
/** PMC System Clock Disable Register */
#define REG_PMC_SCDR (*(uint32_t *)0x400E0604U)
/** PMC Programmable Clock 2 Output Disable bitmask (for `REG_PMC_SCDR`) */
#define REG_PMC_SCDR_PCK2_MASK ((uint32_t)1 << 10)
#define REG_PMC_SCDR_PCK2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock 1 Output Disable bitmask (for `REG_PMC_SCDR`) */
#define REG_PMC_SCDR_PCK1_MASK ((uint32_t)1 << 9)
#define REG_PMC_SCDR_PCK1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock 0 Output Disable bitmask (for `REG_PMC_SCDR`) */
#define REG_PMC_SCDR_PCK0_MASK ((uint32_t)1 << 8)
#define REG_PMC_SCDR_PCK0_BIT ((uint32_t)1 << 8)
/** PMC Disable USB OTG Clock bitmask for UTMI (for `REG_PMC_SCDR`) */
#define REG_PMC_SCDR_UOTGCLK_MASK ((uint32_t)1 << 5)
#define REG_PMC_SCDR_UOTGCLK_BIT ((uint32_t)1 << 5)
/** PMC System Clock Status Register */
#define REG_PMC_SCSR (*(uint32_t *)0x400E0608U)
/** PMC Programmable Clock 2 Output Status bitmask */
#define REG_PMC_SCSR_PCK2_MASK ((uint32_t)1 << 10)
#define REG_PMC_SCSR_PCK2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock 1 Output Status bitmask */
#define REG_PMC_SCSR_PCK1_MASK ((uint32_t)1 << 9)
#define REG_PMC_SCSR_PCK1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock 0 Output Status bitmask */
#define REG_PMC_SCSR_PCK0_MASK ((uint32_t)1 << 8)
#define REG_PMC_SCSR_PCK0_BIT ((uint32_t)1 << 8)
/** PMC USB OTG Clock Status bitmask */
#define REG_PMC_SCSR_UOTGCLK_MASK ((uint32_t)1 << 5)
#define REG_PMC_SCSR_UOTGCLK_BIT ((uint32_t)1 << 5)
/** PMC Peripheral Clock Enable Register 0 */
#define REG_PMC_PCER0 (*(uint32_t *)0x400E0610U)
@ -257,50 +273,66 @@ struct reg_snapshot {
/** PMC Clock Generator Main Oscillator Register */
#define REG_CKGR_MOR (*(uint32_t *)0x400E0620U)
/** PMC Clock Failure Detector Enable bitmask */
#define REG_CKGR_MOR_CFDEN_MASK ((uint32_t)1 << 25)
#define REG_CKGR_MOR_CFDEN_BIT ((uint32_t)1 << 25)
/** PMC Main Oscillator Selection bitmask */
#define REG_CKGR_MOR_MOSCSEL_MASK ((uint32_t)1 << 24)
/** PMC Main Oscillator Password bitmask (shifted 16 to the left, should be `0x37`) */
#define REG_CKGR_MOR_MOSCSEL_BIT ((uint32_t)1 << 24)
/** PMC Main Oscillator Password bitmask */
#define REG_CKGR_MOR_KEY_MASK ((uint32_t)0xFF << 16)
#define REG_CKGR_MOR_KEY_VAL(x) \
( ((uint32_t)(x) << 16) & REG_CKGR_MOR_KEY_MASK )
#define REG_CKGR_MOR_KEY_MAGIC (0x37)
/** PMC Main Crystal Oscillator Start-up Time bitmask (<< 8, 8 bits, unit: clock cycles * 8) */
#define REG_CKGR_MOR_MOSCXTST_MASK ((uint32_t)0xFF << 8)
#define REG_CKGR_MOR_MOSCXTST_VAL(x) \
( ((uint32_t)(x) << 8) & REG_CKGR_MOR_MOSCXTST_MASK )
/** PMC Main On-Chip RC Oscillator Frequency Selection bitmask (<< 4, 2 bits) */
#define REG_CKGR_MOR_MOSCRCF_MASK ((uint32_t)0b111 << 4)
#define REG_CKGR_MOR_MOSCRCF_VAL(x) \
( ((uint32_t)(x) << 4) & REG_CKGR_MOR_MOSCRCF_MASK )
/** PMC Main On-Chip RC Oscillator Enable bitmask */
#define REG_CKGR_MOR_MOSCRCEN_MASK ((uint32_t)1 << 3)
#define REG_CKGR_MOR_MOSCRCEN_BIT ((uint32_t)1 << 3)
/** PMC Main Crystal Oscillator Bypass bitmask */
#define REG_CKGR_MOR_MOSCXTBY_MASK ((uint32_t)1 << 1)
#define REG_CKGR_MOR_MOSCXTBY_BIT ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Enable bitmask */
#define REG_CKGR_MOR_MOSCXTEN_MASK ((uint32_t)1)
#define REG_CKGR_MOR_MOSCXTEN_BIT ((uint32_t)1)
/** PMC Clock Generator Main Clock Frequency Register */
#define REG_CKGR_MCFR (*(const uint32_t *)0x400E0624U)
/** PMC Main Clock Ready bitmask */
#define REG_CKGR_MCFR_MAINFRDY_MASK ((uint32_t)1 << 16)
#define REG_CKGR_MCFR_MAINFRDY_BIT ((uint32_t)1 << 16)
/** PMC Main Clock Frequency bitmask (16-bit, equals amount of main clocks per 16 slow clocks) */
#define REG_CKGR_MCFR_MAINF_MASK ((uint32_t)0xFFFF)
/** PMC Clock Generator PLLA Register */
#define REG_CKGR_PLLAR (*(uint32_t *)0x400E0628U)
/** PMC Clock Generator: Must be set to one when writing to CKGR_PLLAR bitmask */
#define REG_CKGR_PLLAR_ONE_MASK ((uint32_t)1 << 29)
#define REG_CKGR_PLLAR_ONE_BIT ((uint32_t)1 << 29)
/** PMC PLLA Multiplier bitmask (<< 16, 11 bits) */
#define REG_CKGR_PLLAR_MULA_MASK ((uint32_t)0x7FF << 16)
#define REG_CKGR_PLLAR_MULA_VAL(x) \
( ((uint32_t)(x) << 16) & REG_CKGR_PLLAR_MULA_MASK )
/** PMC PLLA Counter bitmask (<< 8, 6 bits) */
#define REG_CKGR_PLLAR_PLLACOUNT_MASK ((uint32_t)0x3F << 8)
#define REG_CKGR_PLLAR_PLLACOUNT_VAL(x) \
( ((uint32_t)(x) << 8) & REG_CKGR_PLLAR_PLLACOUNT_MASK )
/** PMC PLLA Divider bitmask (8 bits) */
#define REG_CKGR_PLLAR_DIVA_MASK ((uint32_t)0xFF)
#define REG_CKGR_PLLAR_DIVA_VAL(x) \
((uint32_t)(x) & REG_CKGR_PLLAR_DIVA_MASK)
/** PMC Master Clock Register */
#define REG_PMC_MCKR (*(uint32_t *)0x400E0630U)
/** PMC Master Clock UPLL Divisor by 2 bitmask */
#define REG_PMC_MCKR_UPLLDIV2_MASK ((uint32_t)1 << 13)
#define REG_PMC_MCKR_UPLLDIV2_BIT ((uint32_t)1 << 13)
/** PMC Master Clock PLLA Divisor by 2 bitmask */
#define REG_PMC_MCKR_PLLADIV2_MASK ((uint32_t)1 << 12)
#define REG_PMC_MCKR_PLLADIV2_BIT ((uint32_t)1 << 12)
/** PMC Master Clock Processor Clock Prescaler bitmask (<< 4, 3 bits) */
#define REG_PMC_MCKR_PRES_MASK ((uint32_t)0x7 << 4)
#define REG_PMC_MCKR_PRES_VAL(x) \
( ((uint32_t)(x) << 4) & REG_PMC_MCKR_PRES_MASK )
/** PMC Master Clock Source Selection bitmask (2 bits) */
#define REG_PMC_MCKR_CSS_MASK ((uint32_t)0x3)
#define REG_PMC_MCKR_CSS_VAL(x) ((uint32_t)(x) & REG_PMC_MCKR_CSS_MASK)
/** PMC USB Clock Register */
#define REG_PMC_USB (*(uint32_t *)0x400E0638U)
@ -313,100 +345,103 @@ struct reg_snapshot {
#define REG_PMC_PCKx (*(uint32_t *)0x400E0640U)
/** PMC Programmable Clock Prescaler bitmask (<< 4, 3 bits) */
#define REG_PMC_PCKx_PRES_MASK ((uint32_t)0x7 << 4)
#define REG_PMC_PCKx_PRES_VAL(x) \
( ((uint32_t)(x) << 4) & REG_PMC_PCKx_PRES_MASK )
/** PMC Master Clock Source Selection bitmask (3 bits) */
#define REG_PMC_PCKx_CSS_MASK ((uint32_t)0x7)
#define REG_PMC_PCKx_CSS_VAL(x) ((uint32_t)(x) & REG_PMC_PCKx_CSS_MASK)
/** PMC Interrupt Enable Register */
#define REG_PMC_IER (*(uint32_t *)0x400E0660U)
/** PMC Clock Failure Detector Event Interrupt Enable bitmask */
#define REG_PMC_IER_CFDEV_MASK ((uint32_t)1 << 18)
#define REG_PMC_IER_CFDEV_BIT ((uint32_t)1 << 18)
/** PMC Main On-Chip RC Status Interrupt Enable bitmask */
#define REG_PMC_IER_MOSCRCS_MASK ((uint32_t)1 << 17)
#define REG_PMC_IER_MOSCRCS_BIT ((uint32_t)1 << 17)
/** PMC Main Oscillator Selection Status Interrupt Enable bitmask */
#define REG_PMC_IER_MOSCSELS_MASK ((uint32_t)1 << 16)
#define REG_PMC_IER_MOSCSELS_BIT ((uint32_t)1 << 16)
/** PMC Programmable Clock Ready 2 Interrupt Enable bitmask */
#define REG_PMC_IER_PCKRDY2_MASK ((uint32_t)1 << 10)
#define REG_PMC_IER_PCKRDY2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock Ready 1 Interrupt Enable bitmask */
#define REG_PMC_IER_PCKRDY1_MASK ((uint32_t)1 << 9)
#define REG_PMC_IER_PCKRDY1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock Ready 0 Interrupt Enable bitmask */
#define REG_PMC_IER_PCKRDY0_MASK ((uint32_t)1 << 8)
#define REG_PMC_IER_PCKRDY0_BIT ((uint32_t)1 << 8)
/** PMC UTMI PLL Lock Interrupt Enable bitmask */
#define REG_PMC_IER_LOCKU_MASK ((uint32_t)1 << 6)
#define REG_PMC_IER_LOCKU_BIT ((uint32_t)1 << 6)
/** PMC Master Clock Ready Interrupt Enable bitmask */
#define REG_PMC_IER_MCKRDY_MASK ((uint32_t)1 << 3)
#define REG_PMC_IER_MCKRDY_BIT ((uint32_t)1 << 3)
/** PMC PLLA Lock Interrupt Enable bitmask */
#define REG_PMC_IER_LOCKA_MASK ((uint32_t)1 << 1)
#define REG_PMC_IER_LOCKA_BIT ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Status Interrupt Enable bitmask */
#define REG_PMC_IER_MOSCXTS_MASK ((uint32_t)1)
#define REG_PMC_IER_MOSCXTS_BIT ((uint32_t)1)
/** PMC Interrupt Disable Register */
#define REG_PMC_IDR (*(uint32_t *)0x400E0664U)
/** PMC Clock Failure Detector Event Interrupt Disable bitmask */
#define REG_PMC_IDR_CFDEV_MASK ((uint32_t)1 << 18)
#define REG_PMC_IDR_CFDEV_BIT ((uint32_t)1 << 18)
/** PMC Main On-Chip RC Status Interrupt Disable bitmask */
#define REG_PMC_IDR_MOSCRCS_MASK ((uint32_t)1 << 17)
#define REG_PMC_IDR_MOSCRCS_BIT ((uint32_t)1 << 17)
/** PMC Main Oscillator Selection Status Interrupt Disable bitmask */
#define REG_PMC_IDR_MOSCSELS_MASK ((uint32_t)1 << 16)
#define REG_PMC_IDR_MOSCSELS_BIT ((uint32_t)1 << 16)
/** PMC Programmable Clock Ready 2 Interrupt Disable bitmask */
#define REG_PMC_IDR_PCKRDY2_MASK ((uint32_t)1 << 10)
#define REG_PMC_IDR_PCKRDY2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock Ready 1 Interrupt Disable bitmask */
#define REG_PMC_IDR_PCKRDY1_MASK ((uint32_t)1 << 9)
#define REG_PMC_IDR_PCKRDY1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock Ready 0 Interrupt Disable bitmask */
#define REG_PMC_IDR_PCKRDY0_MASK ((uint32_t)1 << 8)
#define REG_PMC_IDR_PCKRDY0_BIT ((uint32_t)1 << 8)
/** PMC UTMI PLL Lock Interrupt Disable bitmask */
#define REG_PMC_IDR_LOCKU_MASK ((uint32_t)1 << 6)
#define REG_PMC_IDR_LOCKU_BIT ((uint32_t)1 << 6)
/** PMC Master Clock Ready Interrupt Disable bitmask */
#define REG_PMC_IDR_MCKRDY_MASK ((uint32_t)1 << 3)
#define REG_PMC_IDR_MCKRDY_BIT ((uint32_t)1 << 3)
/** PMC PLLA Lock Interrupt Disable bitmask */
#define REG_PMC_IDR_LOCKA_MASK ((uint32_t)1 << 1)
#define REG_PMC_IDR_LOCKA_BIT ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Status Interrupt Disable bitmask */
#define REG_PMC_IDR_MOSCXTS_MASK ((uint32_t)1)
#define REG_PMC_IDR_MOSCXTS_BIT ((uint32_t)1)
/** PMC Interrupt Status Register */
/** PMC Status Register */
#define REG_PMC_SR (*(const uint32_t *)0x400E0668U)
/** PMC Clock Failure Detector Event Interrupt Status bitmask */
#define REG_PMC_SR_CFDEV_MASK ((uint32_t)1 << 18)
/** PMC Main On-Chip RC Status Interrupt Status bitmask */
#define REG_PMC_SR_MOSCRCS_MASK ((uint32_t)1 << 17)
/** PMC Main Oscillator Selection Status Interrupt Status bitmask */
#define REG_PMC_SR_MOSCSELS_MASK ((uint32_t)1 << 16)
/** PMC Programmable Clock Ready 2 Interrupt Status bitmask */
#define REG_PMC_SR_PCKRDY2_MASK ((uint32_t)1 << 10)
/** PMC Programmable Clock Ready 1 Interrupt Status bitmask */
#define REG_PMC_SR_PCKRDY1_MASK ((uint32_t)1 << 9)
/** PMC Programmable Clock Ready 0 Interrupt Status bitmask */
#define REG_PMC_SR_PCKRDY0_MASK ((uint32_t)1 << 8)
/** PMC UTMI PLL Lock Interrupt Status bitmask */
#define REG_PMC_SR_LOCKU_MASK ((uint32_t)1 << 6)
/** PMC Master Clock Ready Interrupt Status bitmask */
#define REG_PMC_SR_MCKRDY_MASK ((uint32_t)1 << 3)
/** PMC PLLA Lock Interrupt Status bitmask */
#define REG_PMC_SR_LOCKA_MASK ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Status Interrupt Status bitmask */
#define REG_PMC_SR_MOSCXTS_MASK ((uint32_t)1)
/** PMC Clock Failure Detector Event bitmask */
#define REG_PMC_SR_CFDEV_BIT ((uint32_t)1 << 18)
/** PMC Main On-Chip RC Oscillator Status bitmask */
#define REG_PMC_SR_MOSCRCS_BIT ((uint32_t)1 << 17)
/** PMC Main Oscillator Selection Status bitmask */
#define REG_PMC_SR_MOSCSELS_BIT ((uint32_t)1 << 16)
/** PMC Programmable Clock 2 Ready Status bitmask */
#define REG_PMC_SR_PCKRDY2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock 1 Ready Status bitmask */
#define REG_PMC_SR_PCKRDY1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock 0 Ready Status bitmask */
#define REG_PMC_SR_PCKRDY0_BIT ((uint32_t)1 << 8)
/** PMC UTMI PLL Lock Status bitmask */
#define REG_PMC_SR_LOCKU_BIT ((uint32_t)1 << 6)
/** PMC Master Clock Status bitmask */
#define REG_PMC_SR_MCKRDY_BIT ((uint32_t)1 << 3)
/** PMC PLLA Lock Status bitmask */
#define REG_PMC_SR_LOCKA_BIT ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Status bitmask */
#define REG_PMC_SR_MOSCXTS_BIT ((uint32_t)1)
/** PMC Interrupt Mask Register */
#define REG_PMC_IMR (*(const uint32_t *)0x400E066CU)
/** PMC Clock Failure Detector Event Interrupt Mask bitmask */
#define REG_PMC_IMR_CFDEV_MASK ((uint32_t)1 << 18)
#define REG_PMC_IMR_CFDEV_BIT ((uint32_t)1 << 18)
/** PMC Main On-Chip RC Status Interrupt Mask bitmask */
#define REG_PMC_IMR_MOSCRCS_MASK ((uint32_t)1 << 17)
#define REG_PMC_IMR_MOSCRCS_BIT ((uint32_t)1 << 17)
/** PMC Main Oscillator Selection Status Interrupt Mask bitmask */
#define REG_PMC_IMR_MOSCSELS_MASK ((uint32_t)1 << 16)
#define REG_PMC_IMR_MOSCSELS_BIT ((uint32_t)1 << 16)
/** PMC Programmable Clock Ready 2 Interrupt Mask bitmask */
#define REG_PMC_IMR_PCKRDY2_MASK ((uint32_t)1 << 10)
#define REG_PMC_IMR_PCKRDY2_BIT ((uint32_t)1 << 10)
/** PMC Programmable Clock Ready 1 Interrupt Mask bitmask */
#define REG_PMC_IMR_PCKRDY1_MASK ((uint32_t)1 << 9)
#define REG_PMC_IMR_PCKRDY1_BIT ((uint32_t)1 << 9)
/** PMC Programmable Clock Ready 0 Interrupt Mask bitmask */
#define REG_PMC_IMR_PCKRDY0_MASK ((uint32_t)1 << 8)
#define REG_PMC_IMR_PCKRDY0_BIT ((uint32_t)1 << 8)
/** PMC UTMI PLL Lock Interrupt Mask bitmask */
#define REG_PMC_IMR_LOCKU_MASK ((uint32_t)1 << 6)
#define REG_PMC_IMR_LOCKU_BIT ((uint32_t)1 << 6)
/** PMC Master Clock Ready Interrupt Mask bitmask */
#define REG_PMC_IMR_MCKRDY_MASK ((uint32_t)1 << 3)
#define REG_PMC_IMR_MCKRDY_BIT ((uint32_t)1 << 3)
/** PMC PLLA Lock Interrupt Mask bitmask */
#define REG_PMC_IMR_LOCKA_MASK ((uint32_t)1 << 1)
#define REG_PMC_IMR_LOCKA_BIT ((uint32_t)1 << 1)
/** PMC Main Crystal Oscillator Status Interrupt Mask bitmask */
#define REG_PMC_IMR_MOSCXTS_MASK ((uint32_t)1)
#define REG_PMC_IMR_MOSCXTS_BIT ((uint32_t)1)
/* TODO */
@ -414,8 +449,11 @@ struct reg_snapshot {
#define REG_PMC_WPMR (*(uint32_t *)0x400E06E4U)
/** PMC Write Protect Key bitmask (<< 8, 24 bits, needs to be `0x504D43` ("PMC")) */
#define REG_PMC_WPMR_WPKEY_MASK ((uint32_t)0xFFFFFF << 8)
#define REG_PMC_WPMR_WPKEY_VAL(x) \
( ((uint32_t)(x) << 8) & REG_PMC_WPMR_WPKEY_MASK )
#define REG_PMC_WPMR_WPKEY_MAGIC (0x504D43) /* "PMC" in ASCII */
/** PMC Write Protect Enable bitmask */
#define REG_PMC_WPMR_WPEN_MASK ((uint32_t)1)
#define REG_PMC_WPMR_WPEN_BIT ((uint32_t)1)
/** PMC Write Protect Status Register */
#define REG_PMC_WPSR (*(uint32_t *)0x400E06E8U)

@ -27,6 +27,36 @@
#pragma once
/**
* Block the CPU by continuously checking the same expression in an
* infinite loop, until the condition is true. Useful for polling.
*
* @param expr The expression.
*/
#define mom_are_we_there_yet(expr) ({ while (!(expr)); })
/**
* Initialize the system hardware.
* This function is responsible for putting the entire system to a state that
* allows the Kernel to perform its bootstrap procedure and is therefore the
* first thing to be called by `do_bootstrap`. Possible tasks to be dealt with
* here include:
*
* - Performing sanity checks to see if there are any major hardware faults
* - Setting up the CPU frequency and other oscillators
* - Communicating that frequency change to any hardware component that needs
* to know about it (especially the flash controller)
* - Enabling interrupts that are vital for stable operation
*
* If any of this fails, a nonzero value must be returned to indicate the error
* condition. An on-chip LED should be used to "morse" some kind of diagnostic
* message, if the system has one (kind of like BIOS beep codes).
*
* @returns `0` on success, a negative POSIX error code if applicable, or a
* positive (platform-dependant) number on hardware fault.
*/
int sys_init(void);
#if defined(ARCH_ATMEGA328P)
#error "ATmega328p is not implemented (yet?)"
#elif defined(ARCH_AT91SAM3X8E)

@ -30,14 +30,19 @@
#include <ardix/types.h>
#include <arch/hardware.h>
#ifndef SCHED_MAXPROC
#ifndef CONFIG_SCHED_MAXPROC
/** The maximum number of processes. */
#define SCHED_MAXPROC 16
#define CONFIG_SCHED_MAXPROC 16
#endif /* SCHED_MAXPROC */
#if SCHED_MAXPROC > 64
#warning "SCHED_MAXPROC is > 64, this could have a significant impact on performance"
#endif /* SCHED_MAXPROC > 64 */
#if CONFIG_SCHED_MAXPROC > 64
#warning "CONFIG_SCHED_MAXPROC is > 64, this could have a significant impact on performance"
#endif /* CONFIG_SCHED_MAXPROC > 64 */
#ifndef CONFIG_SCHED_INTR_FREQ
/** Frequency (in Hertz) at which a scheduling interrupt should be fired */
#define CONFIG_SCHED_INTR_FREQ 10000U
#endif
enum proc_state {
/** Process is dead / ddoesn't exist */
@ -115,7 +120,7 @@ struct process *sched_process_create(void (*exec)(void));
*
* @param msecs: The amount of milliseconds to (approximately) sleep for.
*/
void sleep(unsigned long int msecs);
void msleep(unsigned long int msecs);
/**
* Block the entire CPU from execution for the specified amount of microseconds.

@ -25,9 +25,11 @@
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch/hardware.h>
#include <arch/sched.h>
#include <ardix/clock.h>
#include <ardix/sched.h>
#include <ardix/string.h>
#include <ardix/types.h>
#include <stddef.h>
@ -36,7 +38,12 @@ extern uint32_t _estack;
struct process *_current_process;
static struct process procs[SCHED_MAXPROC + 1];
/**
* An array of all processes.
* The `pid` not only identifies each process, it is also the index of the
* struct in this array. Unused slots have a `pid` of `-1`, however.
*/
static struct process procs[CONFIG_SCHED_MAXPROC + 1];
int sched_init(void)
{
@ -49,29 +56,56 @@ int sched_init(void)
_current_process->pid = 0;
_current_process->state = PROC_READY;
for (i = 1; i < SCHED_MAXPROC + 1; i++) {
procs[i].state = PROC_DEAD;
for (i = 1; i < CONFIG_SCHED_MAXPROC + 1; i++) {
procs[i].next = NULL;
procs[i].sp = NULL;
procs[i].stack_bottom = NULL;
procs[i].pid = -1;
procs[i].state = PROC_DEAD;
}
i = sched_hwtimer_init(10000);
i = sched_hwtimer_init(CONFIG_SCHED_INTR_FREQ);
return i;
}
/**
* Determine whether the specified process should be executed next.
*
* @param proc: The process.
* @returns Whether `proc` should be next in line for the scheduler.
*/
static inline bool sched_proc_should_run(const struct process *proc)
{
unsigned long int sleep_usecs;
unsigned long int lastexec;
enum proc_state state = proc->state;
if (state == PROC_QUEUE || state == PROC_READY)
return true;
return false;
}
void *sched_process_switch(void *curr_sp)
{
struct process *nextproc = _current_process;
_current_process->sp = curr_sp;
if (_current_process->state != PROC_SLEEP)
_current_process->state = PROC_QUEUE;
sched_interrupts++;
while (true) {
nextproc = nextproc->next;
if (nextproc->state == PROC_QUEUE || nextproc->state == PROC_READY) {
_current_process->state = PROC_QUEUE;
if (sched_proc_should_run(nextproc)) {
nextproc->state = PROC_READY;
_current_process = nextproc;
break;
}
/* TODO: Let the CPU sleep if there is nothing to do */
}
return _current_process->sp;

Loading…
Cancel
Save