-
Notifications
You must be signed in to change notification settings - Fork 193
Expand file tree
/
Copy pathmcal_cpu.cpp
More file actions
150 lines (116 loc) · 5.68 KB
/
mcal_cpu.cpp
File metadata and controls
150 lines (116 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
///////////////////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2007 - 2025.
// Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <mcal_cpu.h>
#include <mcal_gpt.h>
#include <mcal_irq.h>
#include <mcal_led.h>
#include <mcal_osc.h>
#include <mcal_port.h>
#include <mcal_reg.h>
#include <mcal_wdg.h>
extern "C"
{
auto main_c1() -> void;
auto Mcu_StartCore1() -> void;
auto Mcu_StartCoProcessorRiscV() -> void;
extern auto set_cpu_private_timer1(uint32_t) -> void;
extern auto _start() -> void;
}
extern "C"
auto Mcu_StartCore1() -> void
{
// Note: This subroutine is called from core0.
// Firstly we need to unstall core1.
// RTC_CNTL->OPTIONS0.bit.SW_STALL_APPCPU_C0 = 0;
// RTC_CNTL->SW_CPU_STALL.bit.SW_STALL_APPCPU_C1 = 0;
// SYSTEM->CORE_1_CONTROL_0.bit.CONTROL_CORE_1_RUNSTALL = 0;
mcal::reg::reg_access_static<std::uint32_t,
std::uint32_t,
mcal::reg::rtc_cntl::options0,
std::uint32_t { UINT32_C(0) << 0U }>::template reg_msk<std::uint32_t { UINT32_C(0x3) << 0U }>();
mcal::reg::reg_access_static<std::uint32_t,
std::uint32_t,
mcal::reg::rtc_cntl::sw_cpu_stall,
std::uint32_t { UINT32_C(0) << 20U }>::template reg_msk<std::uint32_t { UINT32_C(0x3F) << 0U }>();
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::system::core_1_control_0, static_cast<std::uint32_t>(UINT8_C(0))>::bit_clr();
// Enable the clock for core1.
// SYSTEM->CORE_1_CONTROL_0.bit.CONTROL_CORE_1_CLKGATE_EN = 1;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::system::core_1_control_0, static_cast<std::uint32_t>(UINT8_C(1))>::bit_set();
// Reset core1.
// SYSTEM->CORE_1_CONTROL_0.bit.CONTROL_CORE_1_RESETING = 1;
// SYSTEM->CORE_1_CONTROL_0.bit.CONTROL_CORE_1_RESETING = 0;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::system::core_1_control_0, static_cast<std::uint32_t>(UINT8_C(2))>::bit_set();
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::system::core_1_control_0, static_cast<std::uint32_t>(UINT8_C(2))>::bit_clr();
// Note: In ESP32-S3 when the reset of core1 is released,
// then core1 starts executing the bootROM code. Core1
// subsequently gets stuck in a trap. It is waiting for
// the entry address to be received from core0.
// The send/receive transaction of the entry address is
// carried out via core0 deliberately writing the core1
// entry address in the SYSTEM_CORE_1_CONTROL_1_REG register.
// When this is achieved and done, core1 exits the trap
// and progresses forward.
{
// Set the core1 entry address.
using mcal_reg_access_dynamic_type = mcal::reg::reg_access_dynamic<std::uint32_t, std::uint32_t>;
// SYSTEM->CORE_1_CONTROL_1.reg = (uint32_t) &_start;
mcal_reg_access_dynamic_type::reg_set
(
mcal::reg::system::core_1_control_1,
static_cast<std::uint32_t>(reinterpret_cast<std::uintptr_t>(&_start))
);
}
}
extern "C"
auto Mcu_StartCoProcessorRiscV() -> void
{
// RTC_CNTL->COCPU_CTRL.bit.COCPU_SHUT_RESET_EN = 1;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::cocpu_ctrl, std::uint32_t { UINT8_C(22) }>::bit_set();
// RTC_CNTL->ULP_CP_TIMER.reg = 0;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::ulp_cp_timer, std::uint32_t { UINT8_C(0) }>::reg_set();
// RTC_CNTL->COCPU_CTRL.bit.COCPU_CLK_FO = 1;
// RTC_CNTL->COCPU_CTRL.bit.COCPU_DONE_FORCE = 1;
// RTC_CNTL->COCPU_CTRL.bit.COCPU_CLKGATE_EN = 1;
// RTC_CNTL->COCPU_CTRL.bit.COCPU_SEL = 0;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::cocpu_ctrl, std::uint32_t { UINT8_C( 0) }>::bit_set();
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::cocpu_ctrl, std::uint32_t { UINT8_C(24) }>::bit_set();
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::cocpu_ctrl, std::uint32_t { UINT8_C(27) }>::bit_set();
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::cocpu_ctrl, std::uint32_t { UINT8_C(23) }>::bit_clr();
// RTC_CNTL->ULP_CP_CTRL.bit.ULP_CP_FORCE_START_TOP = 0;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::ulp_cp_ctrl, std::uint32_t { UINT8_C(30) }>::bit_clr();
// RTC_CNTL->ULP_CP_TIMER.bit.ULP_CP_SLP_TIMER_EN = 1;
mcal::reg::reg_access_static<std::uint32_t, std::uint32_t, mcal::reg::rtc_cntl::ulp_cp_timer, std::uint32_t { UINT8_C(31) }>::bit_set();
}
extern "C"
auto main_c1() -> void
{
// Note: This subroutine executes in core1. It has been called
// by the core1 branch of the subroutine _start().
// Set the private cpu timer1 for core1.
set_cpu_private_timer1(mcal::gpt::detail::timer1_reload());
// Enable all interrupts on core1.
mcal::irq::init(nullptr);
// GPIO->OUT.reg |= CORE1_LED;
mcal::led::led1().toggle();
for(;;) { mcal::cpu::nop(); }
}
auto mcal::cpu::post_init() noexcept -> void
{
// Note: This subroutine is called from core0.
// Set the private cpu timer1 for core0.
set_cpu_private_timer1(mcal::gpt::detail::timer1_reload());
// Use core0 to start the RISC-V core.
Mcu_StartCoProcessorRiscV();
// Use core0 to start core1.
Mcu_StartCore1();
}
auto mcal::cpu::init() -> void
{
mcal::wdg::init(nullptr);
mcal::port::init(nullptr);
mcal::osc::init(nullptr);
}