Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions machine/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ pub trait Machinelike {

fn monotonic_now() -> u64;
fn monotonic_freq() -> u64;
fn rtc_raw() -> u64;
fn set_rtc_raw(time: u64) -> i32;
// index 0..32, 0 is used by the RTC
fn rtc_backup_register(index: u8) -> u32;
// index 0..32, 0 is used by the RTC
fn set_rtc_backup_register(index: u8, value: u32);
// Returns the frequency of the machine's systick timer in Hz.
fn systick_freq() -> u64;

Expand Down
21 changes: 20 additions & 1 deletion machine/cortex-m/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ pub struct ArmMachine;
impl hal_api::Machinelike for ArmMachine {
fn init() {
unsafe {
bindings::init_hal();
let ret = bindings::init_hal();
if ret != 0 {
panic!("init_hal failed: {}", ret);
}
bindings::init_debug_uart();
bindings::dwt_init();
}
Expand Down Expand Up @@ -75,6 +78,22 @@ impl hal_api::Machinelike for ArmMachine {
unsafe { bindings::monotonic_freq() }
}

fn rtc_raw() -> u64 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, you assume that every HAL exposes an rtc_raw function that returns a BCD-encoded time. I would not make this the public API. I think it makes more sense to expose POSIX time as universal format and make the conversion HAL/driver defined.

unsafe { bindings::rtc_raw() }
}

fn set_rtc_raw(time: u64) -> i32 {
unsafe { bindings::set_rtc_raw(time) }
}

fn rtc_backup_register(index: u8) -> u32 {
unsafe { bindings::rtc_backup_register(index) }
}

fn set_rtc_backup_register(index: u8, value: u32) {
unsafe { bindings::set_rtc_backup_register(index, value) }
}

fn systick_freq() -> u64 {
unsafe { bindings::systick_freq() }
}
Expand Down
15 changes: 15 additions & 0 deletions machine/cortex-m/src/stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ impl hal_api::Machinelike for StubMachine {
0
}

fn rtc_raw() -> u64 {
0
}

fn set_rtc_raw(_time: u64) -> i32 {
0
}

fn rtc_backup_register(index: u8) -> u32 {
0
}

fn set_rtc_backup_register(index: u8, value: u32) {
}

fn systick_freq() -> u64 {
0
}
Expand Down
167 changes: 163 additions & 4 deletions machine/cortex-m/st/stm32l4/interface/clock.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,106 @@
#include "lib.h"
#include <assert.h>
#include <stm32l4xx_hal.h>
#include "stm32l4xx_hal_rcc.h"
#include <sys/_intsup.h>

static volatile uint64_t monotonic_hi = 0;

#define RTC_BKP_MAGIC 0x4F534952U
#define LSE_READY_TIMEOUT_LOOPS 2000000U
#define LSI_READY_TIMEOUT_LOOPS 200000U

#define ERROR_CONTROL_VOLTAGE_SCALING -1
#define ERROR_RCC_OSC_CONFIG -2
#define ERROR_RCC_CLOCK_CONFIG -3
#define ERROR_RTC_INIT_CLOCK_SOURCE -4
#define ERROR_RTC_INIT -5

static RTC_HandleTypeDef rtc_handle;

static int wait_rcc_ready_flag(uint32_t flag, uint32_t timeout_loops)
{
while (timeout_loops > 0U) {
if (__HAL_RCC_GET_FLAG(flag) != RESET) {
return -1;
}

timeout_loops--;
}

return 0;
}

static HAL_StatusTypeDef select_rtc_clock_source(uint32_t source)
{
RCC_PeriphCLKInitTypeDef periph = {0};

periph.PeriphClockSelection = RCC_PERIPHCLK_RTC;
periph.RTCClockSelection = source;

return HAL_RCCEx_PeriphCLKConfig(&periph);
}

static int init_rtc_clock_source(void)
{
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_HIGH);
__HAL_RCC_LSE_CONFIG(RCC_LSE_ON);

if (!wait_rcc_ready_flag(RCC_FLAG_LSERDY, LSE_READY_TIMEOUT_LOOPS) &&
select_rtc_clock_source(RCC_RTCCLKSOURCE_LSE) == HAL_OK) {
__HAL_RCC_RTC_ENABLE();
return 0;
}

__HAL_RCC_LSE_CONFIG(RCC_LSE_OFF);
__HAL_RCC_LSI_ENABLE();

if (!wait_rcc_ready_flag(RCC_FLAG_LSIRDY, LSI_READY_TIMEOUT_LOOPS) &&
select_rtc_clock_source(RCC_RTCCLKSOURCE_LSI) == HAL_OK) {
__HAL_RCC_RTC_ENABLE();
return 0;
}
return -1;
}

int set_rtc_raw(unsigned long long raw);
int init_rtc(void)
{
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();

// TODO: setup Clock Security System
if (init_rtc_clock_source()) {
return ERROR_RTC_INIT_CLOCK_SOURCE;
}

rtc_handle.Instance = RTC;
rtc_handle.Init.HourFormat = RTC_HOURFORMAT_24;
rtc_handle.Init.AsynchPrediv = 0x7FU;
rtc_handle.Init.SynchPrediv = 0x00FFU;
Comment thread
gkuznik marked this conversation as resolved.
rtc_handle.Init.OutPut = RTC_OUTPUT_DISABLE;
rtc_handle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
rtc_handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
rtc_handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if (HAL_RTC_Init(&rtc_handle) != HAL_OK) {
return ERROR_RTC_INIT;
}

if (HAL_RTCEx_BKUPRead(&rtc_handle, RTC_BKP_DR0) != RTC_BKP_MAGIC) {
// Sat 01.01.2000
unsigned long long time = ((uint64_t)0) |
((uint64_t)0 << 8U) |
((uint64_t)0 << 16U) |
((uint64_t)RTC_WEEKDAY_SATURDAY << 32U) |
((uint64_t)RTC_MONTH_JANUARY << 40U) |
((uint64_t)1 << 48U) |
((uint64_t)0 << 56U);
return set_rtc_raw(time);
}
return 0;
}

static void init_monotonic_timer(void)
{
const uint32_t target_hz = 1000000U;
Expand Down Expand Up @@ -53,7 +151,7 @@ void tim2_hndlr(void)
}
}

void init_clock_cfg(void)
int init_clock_cfg(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
Expand All @@ -62,7 +160,7 @@ void init_clock_cfg(void)
__HAL_RCC_PWR_CLK_ENABLE();

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
while (1) {}
return ERROR_CONTROL_VOLTAGE_SCALING;
}

/* HSI16 -> PLL -> 80 MHz SYSCLK */
Expand All @@ -79,7 +177,7 @@ void init_clock_cfg(void)
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // arbitrary unless you use PLLQ

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
while (1) {}
return ERROR_RCC_OSC_CONFIG;
}

RCC_ClkInitStruct.ClockType =
Expand All @@ -94,11 +192,12 @@ void init_clock_cfg(void)
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
while (1) {}
return ERROR_RCC_CLOCK_CONFIG;
}

SystemCoreClockUpdate();
init_monotonic_timer();
return init_rtc();
}

unsigned long long monotonic_now(void)
Expand Down Expand Up @@ -127,4 +226,64 @@ unsigned long long monotonic_now(void)
unsigned long long monotonic_freq(void)
{
return 1000000ULL;
}

long rtc_backup_register(unsigned index)
{
return HAL_RTCEx_BKUPRead(&rtc_handle, RTC_BKP_DR0 + index);
}

void set_rtc_backup_register(unsigned index, long value)
{
assert(index != 0 && "Register 0 is reserved for RTC init");
HAL_RTCEx_BKUPWrite(&rtc_handle, RTC_BKP_DR0 + index, value);
}

unsigned long long rtc_raw(void)
{
RTC_TimeTypeDef time = {0};
RTC_DateTypeDef date = {0};

if (HAL_RTC_GetTime(&rtc_handle, &time, RTC_FORMAT_BCD) != HAL_OK) {
return -1U;
}

if (HAL_RTC_GetDate(&rtc_handle, &date, RTC_FORMAT_BCD) != HAL_OK) {
return -2U;
}

return ((uint64_t)time.Hours) |
((uint64_t)time.Minutes << 8U) |
((uint64_t)time.Seconds << 16U) |
((uint64_t)date.WeekDay << 32U) |
((uint64_t)date.Month << 40U) |
((uint64_t)date.Date << 48U) |
((uint64_t)date.Year << 56U);
}

int set_rtc_raw(unsigned long long raw)
{
RTC_TimeTypeDef rtc_time = {0};
RTC_DateTypeDef rtc_date = {0};

rtc_time.Hours = (uint8_t)(raw & 0xFFU);
rtc_time.Minutes = (uint8_t)((raw >> 8U) & 0xFFU);
rtc_time.Seconds = (uint8_t)((raw >> 16U) & 0xFFU);
rtc_time.TimeFormat = RTC_HOURFORMAT_24;

rtc_date.WeekDay = (uint8_t)((raw >> 32U) & 0xFFU);
rtc_date.Month = (uint8_t)((raw >> 40U) & 0xFFU);
rtc_date.Date = (uint8_t)((raw >> 48U) & 0xFFU);
rtc_date.Year = (uint8_t)((raw >> 56U) & 0xFFU);

if (HAL_RTC_SetTime(&rtc_handle, &rtc_time, RTC_FORMAT_BCD) != HAL_OK) {
return -1;
}

if (HAL_RTC_SetDate(&rtc_handle, &rtc_date, RTC_FORMAT_BCD) != HAL_OK) {
return -2;
}

HAL_RTCEx_BKUPWrite(&rtc_handle, RTC_BKP_DR0, RTC_BKP_MAGIC);
return 0;
}
7 changes: 6 additions & 1 deletion machine/cortex-m/st/stm32l4/interface/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// lib.c
unsigned long long systick_freq(void);
void init_hal(void);
int init_hal(void);

// uart.c
int init_debug_uart(void);
Expand All @@ -23,3 +23,8 @@ void SystemClock_Config(void);

unsigned long long monotonic_now(void);
unsigned long long monotonic_freq(void);
unsigned long long rtc_raw(void);
int set_rtc_raw(unsigned long long time);

unsigned long rtc_backup_register(unsigned char index);
void set_rtc_backup_register(unsigned char index, unsigned long value);
21 changes: 16 additions & 5 deletions machine/cortex-m/st/stm32l4/interface/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,36 @@ static void enable_faults(void) {
__DSB();
}

static void init_systick(void) {
HAL_SYSTICK_Config(SystemCoreClock / 1000); // Configure SysTick to interrupt every 1 ms
static int init_systick(void) {
if (HAL_SYSTICK_Config(SystemCoreClock / 1000)) // Configure SysTick to interrupt every 1 ms
return -1;
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
return 0;
}

unsigned long long systick_freq(void) {
return 1000;
}

void init_hal(void) {
int init_hal(void) {
#if OSIRIS_TUNING_ENABLEFPU
init_fpu();
#endif
HAL_Init();

enable_faults();

init_clock_cfg();
init_systick();
int ret = init_clock_cfg();
if (ret != 0) {
return ret;
}

ret = init_systick();
if (ret != 0) {
return ret;
}

return 0;
}

void HAL_MspInit(void) {
Expand Down
2 changes: 1 addition & 1 deletion machine/cortex-m/st/stm32l4/interface/lib.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#pragma once

void init_clock_cfg(void);
int init_clock_cfg(void);
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub unsafe extern "C" fn kernel_init() -> ! {
idle::init();
kprintln!("Idle thread initialized.");

time::init();
kprintln!("Time thread initialized.");

let (cyc, _ns) = hal::Machine::bench_end();
kprintln!("Kernel init took {} cycles.", cyc);

Expand Down
Loading
Loading