add Chapter12

This commit is contained in:
Amar Mahmutbegovic
2024-10-21 05:39:20 +02:00
parent 87087b3bfb
commit a73a8f62f1
209 changed files with 303106 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
#include <cstdint>
#include <cstdio>
#include <type_traits>
#include <stm32f072xb.h>
#include <hal.hpp>
#include <uart_stm32.hpp>
#include <retarget.hpp>
struct read_access{};
struct write_access{};
struct read_write_access : read_access, write_access {};
template<std::uintptr_t Address, typename Access = read_write_access, typename T = std::uint32_t>
struct reg {
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<read_access, Access_>, T> read() {
return *reinterpret_cast<volatile T*>(Address);
}
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<write_access, Access_>, void> write(T val) {
*reinterpret_cast<volatile T*>(Address) = val;
}
};
using rcc = reg<0x40021000, read_write_access>;
int main()
{
hal::init();
hal::uart_stm32 uart(USART2);
uart.init();
retarget::set_stdio_uart(&uart);
printf("Hello world\r\n");
auto const print_reg = [](volatile uint32_t * reg) {
printf("========================\r\n");
printf("Reg address = %p\r\n", reinterpret_cast<volatile void*>(reg));
printf("Reg value = 0x%08lX\r\n", *reg);
};
print_reg(&(RCC->CR));
// RCC->CR = 0xDEADBEEF;
rcc::write(0xDEADBEEF);
auto val = rcc::read();
printf("val = %ld\r\n", val);
print_reg(&(RCC->CR));
while(true)
{
}
}

View File

@@ -0,0 +1,168 @@
#include <cstdint>
#include <cstdio>
#include <stm32f072xb.h>
#include <hal.hpp>
#include <uart_stm32.hpp>
#include <retarget.hpp>
struct read_access{};
struct write_access{};
struct read_write_access : read_access, write_access {};
template<typename BitField, typename Reg, typename T>
concept BitFieldConcept =
std::is_same_v<Reg, typename BitField::reg> &&
std::is_enum_v<typename BitField::value> &&
std::is_same_v<std::underlying_type_t<typename BitField::value>, T>;
template<std::uintptr_t Address, typename Access = read_write_access, typename T = std::uint32_t>
struct reg {
using RegType = T;
using ThisReg = reg<Address, Access, T>; // Type alias for the current instantiation
template<typename BitField>
requires BitFieldConcept<BitField, ThisReg, T> // Apply the concept
static void set(BitField::value bits_val) {
auto reg_value = read();
reg_value &= ~BitField::c_mask;
reg_value |= (static_cast<T>(bits_val) << BitField::c_position) & BitField::c_mask;
write(reg_value);
}
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<read_access, Access_>, T> read() {
return *reinterpret_cast<volatile T*>(Address);
}
private:
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<write_access, Access_>, void> write(T val) {
*reinterpret_cast<volatile T*>(Address) = val;
}
};
struct timer2_traits {
constexpr static std::uintptr_t base_address = 0x40000000;
constexpr static IRQn_Type irqn = TIM2_IRQn;
constexpr static std::uint32_t arr_bit_mask = 0xFFFFFFFF;
};
struct timer3_traits {
constexpr static std::uintptr_t base_address = 0x40000400;
constexpr static IRQn_Type irqn = TIM3_IRQn;
constexpr static std::uint32_t arr_bit_mask = 0xFFFF;
};
template <typename TimerTraits>
struct timer {
constexpr static std::uintptr_t base_address = TimerTraits::base_address;
using cr1 = reg<base_address + 0x00>;
using dier = reg<base_address + 0x0C>;
using sr = reg<base_address + 0x10>;
using psc = reg<base_address + 0x28, read_write_access, std::uint32_t>;
using arr = reg<base_address + 0x2C>;
template<auto Bits, typename Reg, uint32_t Mask, uint32_t Pos = 0>
struct reg_bits {
using reg = Reg;
using T = reg::RegType;
static_assert(std::is_same_v<T, decltype(Bits)>);
static constexpr T c_position = Pos;
static constexpr T c_mask = (Mask << c_position);
static_assert(Bits <= Mask);
enum class value : T {
val = Bits
};
};
template<typename Reg, uint32_t Pos>
struct reg_bits_enable_disable {
using reg = Reg;
using T = reg::RegType;
static constexpr T c_position = Pos;
static constexpr T c_mask = (0x1UL << c_position);
enum class value : T {
disable = 0,
enable = 1
};
};
template<auto Bits>
using psc_bits = reg_bits<Bits, psc, static_cast<uint32_t>(0xFFFF)>;
template<auto Bits>
using arr_bits = reg_bits<Bits, arr, TimerTraits::arr_bit_mask>;
using uie = reg_bits_enable_disable<dier, 0UL>;
using cen = reg_bits_enable_disable<cr1, 0UL>;
using uif = reg_bits_enable_disable<sr, 0UL>;
template<std::uint32_t Period>
static void start() {
constexpr std::uint32_t prescaler = 10000000 / 1000 - 1;
constexpr std::uint32_t auto_reload = Period - 1;
psc::template set<psc_bits<prescaler>>(psc_bits<prescaler>::value::val);
arr::template set<arr_bits<auto_reload>>(arr_bits<auto_reload>::value::val);
dier::template set<uie>(uie::value::enable);
NVIC_SetPriority(TimerTraits::irqn, 1);
NVIC_EnableIRQ(TimerTraits::irqn);
cr1::template set<cen>(cen::value::enable);
}
};
using timer2 = timer<timer2_traits>;
using timer3 = timer<timer3_traits>;
// Timer interrupt handler
extern "C" void TIM2_IRQHandler(void)
{
if (timer2::sr::read() & TIM_SR_UIF) // Check if update interrupt flag is set
{
timer2::sr::set<timer2::uif>(timer2::uif::value::disable);
printf("TIM2 IRQ..\r\n");
}
}
// Timer interrupt handler
extern "C" void TIM3_IRQHandler(void)
{
if (timer3::sr::read() & TIM_SR_UIF) // Check if update interrupt flag is set
{
timer3::sr::set<timer3::uif>(timer3::uif::value::disable);
printf("TIM3 IRQ..\r\n");
}
}
int main()
{
hal::init();
hal::uart_stm32 uart(USART2);
uart.init();
retarget::set_stdio_uart(&uart);
timer2::start<1000>();
timer3::start<500>();
while(true)
{
}
}

View File

@@ -0,0 +1,108 @@
#include <cstdint>
#include <cstdio>
#include <stm32f072xb.h>
#include <hal.hpp>
#include <uart_stm32.hpp>
#include <retarget.hpp>
struct read_access{};
struct write_access{};
struct read_write_access : read_access, write_access {};
template<typename BitField, typename Reg, typename T>
concept BitFieldConcept =
std::is_same_v<Reg, typename BitField::reg> &&
std::is_enum_v<typename BitField::value> &&
std::is_same_v<std::underlying_type_t<typename BitField::value>, T>;
template<std::uintptr_t Address, typename Access = read_write_access, typename T = std::uint32_t>
struct reg {
using RegType = T;
using ThisReg = reg<Address, Access, T>; // Type alias for the current instantiation
template<typename BitField>
requires BitFieldConcept<BitField, ThisReg, T> // Apply the concept
static void set(BitField::value bits_val) {
auto reg_value = read();
reg_value &= ~BitField::c_mask;
reg_value |= (static_cast<T>(bits_val) << BitField::c_position) & BitField::c_mask;
write(reg_value);
}
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<read_access, Access_>, T> read() {
return *reinterpret_cast<volatile T*>(Address);
}
private:
template <typename Access_ = Access>
static std::enable_if_t<std::is_base_of_v<write_access, Access_>, void> write(T val) {
*reinterpret_cast<volatile T*>(Address) = val;
}
};
using rcc = reg<0x40021000>;
struct hsion {
using reg = rcc;
using T = reg::RegType;
static constexpr T c_position = 0U;
static constexpr T c_mask = (1U << c_position);
enum class value : T {
disable = 0U,
enable = 1U,
};
};
template<auto Bits>
struct hsi_trim {
using reg = rcc;
using T = reg::RegType;
static_assert(std::is_same_v<T, decltype(Bits)>);
static constexpr T c_position = 3;
static constexpr T c_mask = (0x1F << c_position);
static_assert(Bits <= 0x1F);
enum class value : T {
val = Bits
};
};
int main()
{
hal::init();
hal::uart_stm32 uart(USART2);
uart.init();
retarget::set_stdio_uart(&uart);
printf("Hello world\r\n");
auto const print_reg = [](volatile uint32_t * reg) {
printf("========================\r\n");
printf("Reg address = %p\r\n", reinterpret_cast<volatile void*>(reg));
printf("Reg value = 0x%08lX\r\n", *reg);
};
print_reg(&(RCC->CR));
rcc::set<hsion>(hsion::value::disable);
print_reg(&(RCC->CR));
rcc::set<hsi_trim<0xFLU>>(hsi_trim<0xFLU>::value::val);
print_reg(&(RCC->CR));
while(true)
{
}
}