diff --git a/examples/chapter09_08a/build.bat b/examples/chapter09_08a/build.bat
index 7d8f3b968..a53396a57 100644
--- a/examples/chapter09_08a/build.bat
+++ b/examples/chapter09_08a/build.bat
@@ -54,6 +54,9 @@
@echo.Compile : mcal_cpu.cpp to bin/mcal_cpu.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_cpu.cpp -o bin/mcal_cpu.o
+@echo.Compile : mcal_eep.cpp to bin/mcal_eep.o
+@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_eep.cpp -o bin/mcal_eep.o
+
@echo.Compile : mcal_gpt.cpp to bin/mcal_gpt.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_gpt.cpp -o bin/mcal_gpt.o
@@ -78,15 +81,15 @@
@echo.Compile : mcal_pwm.cpp to bin/mcal_pwm.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_pwm.cpp -o bin/mcal_pwm.o
+@echo.Compile : mcal_spi.cpp to bin/mcal_spi.o
+@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_spi.cpp -o bin/mcal_spi.o
+
@echo.Compile : mcal_wdg.cpp to bin/mcal_wdg.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/mcal/avr/mcal_wdg.cpp -o bin/mcal_wdg.o
@echo.Compile : os.cpp to bin/os.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/os/os.cpp -o bin/os.o
-@echo.Compile : os.cpp to bin/os_task_control_block.o
-@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/os/os_task_control_block.cpp -o bin/os_task_control_block.o
-
@echo.Compile : sys_idle.cpp to bin/sys_idle.o
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c src/sys/idle/sys_idle.cpp -o bin/sys_idle.o
@@ -109,7 +112,7 @@
@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x c++ %CFLAGS% %CPPFLAGS% %CINCLUDES% -c target/micros/avr/startup/int_vect.cpp -o bin/int_vect.o
@echo.Link : objects to bin/chapter09_08a.elf
-@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x none -mrelax -nostartfiles %CFLAGS% %CPPFLAGS% %CINCLUDES% -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter09_08a.map bin/app_led.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_gpt.o bin/mcal_led.o bin/mcal_led_rgb.o bin/mcal_led_sys_start_interface.o bin/mcal_irq.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_wdg.o bin/os.o bin/os_task_control_block.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter09_08a.elf
+@%TOOL_PATH%\%TOOL_PREFIX%-g++ -x none -mrelax -nostartfiles %CFLAGS% %CPPFLAGS% %CINCLUDES% -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter09_08a.map bin/app_led.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_eep.o bin/mcal_gpt.o bin/mcal_led.o bin/mcal_led_rgb.o bin/mcal_led_sys_start_interface.o bin/mcal_irq.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_spi.o bin/mcal_wdg.o bin/os.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter09_08a.elf
@echo.
@echo.Extract : executable hex file : from bin/chapter09_08a.elf
diff --git a/examples/chapter09_08a/build.sh b/examples/chapter09_08a/build.sh
index b280d4950..44870cec8 100755
--- a/examples/chapter09_08a/build.sh
+++ b/examples/chapter09_08a/build.sh
@@ -12,7 +12,7 @@
#
# If command
# /usr/bin/avr-g++
-# installed, e.g. via command apt-get install gcc-avr avr-libc
+# installed, e.g. via command sudo apt-get install gcc-avr avr-libc
# then:
# ./build.sh
#
@@ -73,6 +73,9 @@ $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/mcal
echo "Compile : mcal_cpu.cpp to bin/mcal_cpu.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_cpu.cpp -o bin/mcal_cpu.o
+echo "Compile : mcal_eep.cpp to bin/mcal_eep.o"
+$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_eep.cpp -o bin/mcal_eep.o
+
echo "Compile : mcal_led.cpp to bin/mcal_led.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_led.cpp -o bin/mcal_led.o
@@ -97,15 +100,15 @@ $TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/
echo "Compile : mcal_pwm.cpp to bin/mcal_pwm.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_pwm.cpp -o bin/mcal_pwm.o
+echo "Compile : mcal_spi.cpp to bin/mcal_spi.o"
+$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_spi.cpp -o bin/mcal_spi.o
+
echo "Compile : mcal_wdg.cpp to bin/mcal_wdg.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/mcal/avr/mcal_wdg.cpp -o bin/mcal_wdg.o
echo "Compile : os.cpp to bin/os.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/os/os.cpp -o bin/os.o
-echo "Compile : os.cpp to bin/os_task_control_block.o".
-$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/os/os_task_control_block.cpp -o bin/os_task_control_block.o
-
echo "Compile : sys_idle.cpp to bin/sys_idle.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c src/sys/idle/sys_idle.cpp -o bin/sys_idle.o
@@ -128,7 +131,7 @@ echo "Compile : int_vect.cpp to bin/int_vect.o"
$TOOL_PATH/$TOOL_PREFIX-g++ -x c++ $CFLAGS $CPPFLAGS $CINCLUDES -c target/micros/avr/startup/int_vect.cpp -o bin/int_vect.o
echo "Link : objects to bin/chapter09_08a.elf"
-$TOOL_PATH/$TOOL_PREFIX-g++ -x none -mrelax -nostartfiles $CFLAGS $CPPFLAGS $CINCLUDES -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter09_08a.map bin/app_led.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_led_rgb.o bin/mcal_led_sys_start_interface.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_wdg.o bin/os.o bin/os_task_control_block.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter09_08a.elf
+$TOOL_PATH/$TOOL_PREFIX-g++ -x none -mrelax -nostartfiles $CFLAGS $CPPFLAGS $CINCLUDES -Wl,--gc-sections -Wl,-Ttarget/micros/avr/make/avr.ld,-Map,bin/chapter09_08a.map bin/app_led.o bin/mcal.o bin/mcal_gcc_cxx_completion.o bin/mcal_cpu.o bin/mcal_eep.o bin/mcal_gpt.o bin/mcal_irq.o bin/mcal_led.o bin/mcal_led_rgb.o bin/mcal_led_sys_start_interface.o bin/mcal_osc.o bin/mcal_port.o bin/mcal_pwm.o bin/mcal_spi.o bin/mcal_wdg.o bin/os.o bin/sys_idle.o bin/sys_mon.o bin/sys_start.o bin/crt0.o bin/crt0_init_ram.o bin/crt1.o bin/int_vect.o -o bin/chapter09_08a.elf
echo
echo "Extract : executable hex file : from bin/chapter09_08a.elf"
diff --git a/examples/chapter09_08a/chapter09_08a.cppproj b/examples/chapter09_08a/chapter09_08a.cppproj
index 0ddc5d723..e480ff747 100644
--- a/examples/chapter09_08a/chapter09_08a.cppproj
+++ b/examples/chapter09_08a/chapter09_08a.cppproj
@@ -148,6 +148,8 @@
+
+
@@ -174,12 +176,21 @@
compile
+
+ compile
+
compile
compile
+
+ compile
+
+
+ compile
+
compile
@@ -237,6 +248,12 @@
compile
+
+ compile
+
+
+ compile
+
compile
@@ -267,12 +284,18 @@
compile
+
+ compile
+
compile
compile
+
+ compile
+
compile
@@ -297,6 +320,24 @@
compile
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
+
+ compile
+
compile
@@ -306,9 +347,6 @@
compile
-
- compile
-
compile
@@ -366,24 +404,42 @@
compile
-
+
compile
-
+
+ compile
+
+
compile
compile
+
+ compile
+
+
+ compile
+
compile
+
+ compile
+
compile
+
+ compile
+
compile
+
+ compile
+
compile
@@ -399,6 +455,9 @@
compile
+
+ compile
+
compile
@@ -458,6 +517,9 @@
compile
+
+ compile
+
compile
@@ -515,6 +577,9 @@
compile
+
+ compile
+
compile
@@ -530,6 +595,9 @@
compile
+
+ compile
+
compile
diff --git a/examples/chapter09_08a/chapter09_08a.vcxproj b/examples/chapter09_08a/chapter09_08a.vcxproj
index 8c179aeac..17a5ef22b 100644
--- a/examples/chapter09_08a/chapter09_08a.vcxproj
+++ b/examples/chapter09_08a/chapter09_08a.vcxproj
@@ -106,6 +106,10 @@
true
true
+
+ true
+ true
+
true
true
@@ -138,6 +142,10 @@
true
true
+
+ true
+ true
+
true
true
@@ -147,6 +155,8 @@
true
true
+
+
@@ -154,10 +164,13 @@
+
+
+
+
-
@@ -179,10 +192,18 @@
+
+ true
+ true
+
true
true
+
+ true
+ true
+
true
true
@@ -227,14 +248,26 @@
true
true
+
+ true
+ true
+
+
+ true
+ true
+
true
true
+
+
+
+
@@ -244,9 +277,12 @@
+
+
-
+
+
@@ -255,6 +291,12 @@
+
+
+
+
+
+
@@ -313,6 +355,8 @@
+
+
true
diff --git a/examples/chapter09_08a/chapter09_08a.vcxproj.filters b/examples/chapter09_08a/chapter09_08a.vcxproj.filters
index 270792a69..2a0f60b9f 100644
--- a/examples/chapter09_08a/chapter09_08a.vcxproj.filters
+++ b/examples/chapter09_08a/chapter09_08a.vcxproj.filters
@@ -64,6 +64,12 @@
{a0535197-0c3a-4d51-b990-93cef869c23a}
+
+ {7c8b3a64-0d36-4a18-833c-e53da967214d}
+
+
+ {b5e41e8f-8ae5-4e62-9577-1349fe2fa44a}
+
@@ -75,9 +81,6 @@
src\os
-
- src\os
-
src\sys\idle
@@ -90,30 +93,6 @@
src\app\led
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
src\util\STL\impl
@@ -126,6 +105,21 @@
src\util\STD_LIBC
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
src\mcal\avr
@@ -141,23 +135,56 @@
src\mcal\avr
-
+
src\mcal\avr
-
+
src\mcal\avr
-
- src\mcal\avr
+
+ src\mcal\win32
-
- src\mcal\avr
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
src\mcal\win32
-
- src\mcal\avr
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
@@ -176,33 +203,9 @@
src\util\STL_C++XX_stdfloat
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
src
-
- src\mcal\win32
-
src\util\memory
@@ -215,21 +218,6 @@
src\util\memory
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
-
- src\mcal\win32
-
src\util\STL\impl
@@ -296,6 +284,51 @@
src\util\utility
+
+ src\mcal_led
+
+
+ src\mcal_led
+
+
+ src\mcal_led
+
+
+ src\mcal_led
+
+
+ src\mcal_led
+
+
+ src\mcal_led
+
+
+ src\mcal
+
+
+ src\mcal
+
+
+ src\util\STL
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
+
+ src\mcal\avr
+
src\mcal\avr
@@ -320,53 +353,98 @@
src\mcal\avr
-
+
src\mcal\avr
-
+
src\mcal\avr
-
+
src\mcal\avr
-
- src\mcal\avr
+
+ src\mcal
-
- src\mcal_led
+
+ src\mcal
-
- src\mcal_led
+
+ src\mcal\win32
-
- src\mcal_led
+
+ src\mcal\win32
-
- src\mcal_led
+
+ src\mcal\win32
-
- src\mcal_led
+
+ src\mcal\win32
-
- src\mcal_led
+
+ src\mcal\win32
src\mcal\win32
-
- src\mcal\avr
+
+ src\mcal\win32
+
+
+ src\mcal\win32
src\mcal\win32
-
- src\mcal
+
+ src\mcal\win32
-
- src\mcal
+
+ src\mcal\win32
-
- src\util\STL
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal\win32
+
+
+ src\mcal_pwm
+
+
+ src\mcal_pwm
+
+
+ src\mcal_pwm
+
+
+ src\mcal_pwm
+
+
+ src\mcal_spi
+
+
+ src\mcal_spi
@@ -493,6 +571,8 @@
src\util\STL
+
+
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_benchmark.h b/examples/chapter09_08a/src/mcal/avr/mcal_benchmark.h
new file mode 100644
index 000000000..d57ed58ce
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_benchmark.h
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014 - 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)
+//
+
+#ifndef MCAL_BENCHMARK_2014_04_16_H
+ #define MCAL_BENCHMARK_2014_04_16_H
+
+ #include
+ #include
+
+ #include
+
+ namespace mcal
+ {
+ namespace benchmark
+ {
+ using benchmark_port_type = mcal::port::port_pin;
+ }
+ }
+
+#endif // MCAL_BENCHMARK_2014_04_16_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_eep.cpp b/examples/chapter09_08a/src/mcal/avr/mcal_eep.cpp
new file mode 100644
index 000000000..1a36498c9
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_eep.cpp
@@ -0,0 +1,105 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2018 - 2024.
+// 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
+#include
+#include
+
+namespace local
+{
+ auto mcal_eep_is_busy() -> bool;
+
+ auto mcal_eep_is_busy() -> bool
+ {
+ return (mcal::reg::reg_access_static::bit_get());
+ }
+} // namespace local
+
+auto mcal::eep::init(const config_type*) -> void
+{
+}
+
+auto mcal::eep::write(const address_type addr, const std::uint8_t data) -> void
+{
+ while(local::mcal_eep_is_busy())
+ {
+ mcal::cpu::nop();
+ }
+
+ // Write the address register.
+ mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eear, addr);
+
+ // Write the data register.
+ mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eedr, data);
+
+ // Set eecr.eempe (bit 2).
+ mcal::reg::reg_access_static::bit_set();
+
+ // Set eecr.eepe (bit 1).
+ mcal::reg::reg_access_static::bit_set();
+}
+
+auto mcal::eep::read(const address_type addr) -> std::uint8_t
+{
+ while(local::mcal_eep_is_busy())
+ {
+ mcal::cpu::nop();
+ }
+
+ // Write the address register.
+ mcal::reg::reg_access_dynamic::reg_set(mcal::reg::eear, addr);
+
+ // Set eecr.eere (bit 0).
+ mcal::reg::reg_access_static::bit_set();
+
+ // Read one data byte.
+ const std::uint8_t data =
+ mcal::reg::reg_access_static::reg_get();
+
+ return data;
+}
+
+/*
+#define EERE 0
+#define EEPE 1
+#define EEMPE 2
+#define EERIE 3
+#define EEPM0 4
+#define EEPM1 5
+*/
+
+/*
+while(EECR & (1 << EEPE));
+EEAR = uiAddress;
+EEDR = ucData;
+EECR |= 1 << EEMPE;
+EECR |= 1 << EEPE;
+*/
+
+/*
+ while (EECR & (1 << EEPE));
+ EEAR = uiAddress;
+ EECR |= (1 << EERE);
+ return EEDR;
+*/
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_eep.h b/examples/chapter09_08a/src/mcal/avr/mcal_eep.h
new file mode 100644
index 000000000..aa875539a
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_eep.h
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2018 - 2024.
+// 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)
+//
+
+#ifndef MCAL_EEP_2018_12_15_H
+ #define MCAL_EEP_2018_12_15_H
+
+ #include
+
+ namespace mcal
+ {
+ namespace eep
+ {
+ using config_type = void;
+ using address_type = std::uint_fast16_t;
+
+ auto init(const config_type*) -> void;
+
+ auto write(const address_type addr, const std::uint8_t data)-> void;
+ auto read (const address_type addr) -> std::uint8_t;
+ }
+ }
+
+#endif // MCAL_EEP_2018_12_15_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_gpt.cpp b/examples/chapter09_08a/src/mcal/avr/mcal_gpt.cpp
index db5d8dd8d..1c715a12b 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_gpt.cpp
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_gpt.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -8,75 +8,101 @@
#include
#include
+#include
+
namespace
{
// The one (and only one) system tick.
- volatile mcal::gpt::value_type mcal_gpt_system_tick;
+ volatile auto mcal_gpt_system_tick = mcal::gpt::value_type { };
- bool& gpt_is_initialized() __attribute__((used, noinline));
+ auto gpt_is_initialized() -> bool& ATTRIBUTE(used, noinline);
- bool& gpt_is_initialized()
+ auto gpt_is_initialized() -> bool&
{
- static bool is_init = bool();
+ static auto is_init = bool { };
return is_init;
}
}
extern "C"
-void __vector_16() __attribute__((signal, used, externally_visible));
+auto __vector_16() -> void ATTRIBUTE(signal, used, externally_visible);
-void __vector_16()
+auto __vector_16() -> void
{
- // Increment the 32-bit system tick with 0x80, representing 128 microseconds.
- const mcal::gpt::value_type new_tick = mcal_gpt_system_tick + static_cast(0x80U);
+ // Increment the 32-bit system tick with 0x100, representing 256 [(1/2) us].
+ // This is basically the roll-over of the 8-bit timer0 at 2MHz each 128us.
+
+ const auto new_tick =
+ static_cast
+ (
+ mcal_gpt_system_tick + static_cast(UINT16_C(0x100))
+ );
mcal_gpt_system_tick = new_tick;
}
-void mcal::gpt::init(const config_type*)
+auto mcal::gpt::init(const config_type*) -> void
{
- if(gpt_is_initialized() == false)
+ if(!gpt_is_initialized())
{
// Clear the timer0 overflow flag.
- mcal::reg::reg_access_static::reg_set();
+ mcal::reg::reg_access_static(UINT8_C(0x01))>::reg_set();
// Enable the timer0 overflow interrupt.
- mcal::reg::reg_access_static::reg_set();
+ mcal::reg::reg_access_static(UINT8_C(0x01))>::reg_set();
// Set the timer0 clock source to f_osc/8 = 2MHz and begin counting.
- mcal::reg::reg_access_static::reg_set();
+ mcal::reg::reg_access_static(UINT8_C(0x02))>::reg_set();
// Set the is-initialized indication flag.
gpt_is_initialized() = true;
}
}
-mcal::gpt::value_type mcal::gpt::secure::get_time_elapsed()
+auto mcal::gpt::secure::get_time_elapsed() -> mcal::gpt::value_type
{
if(gpt_is_initialized())
{
// Return the system tick using a multiple read to ensure data consistency.
- typedef std::uint8_t timer_address_type;
- typedef std::uint8_t timer_register_type;
+ using timer_address_type = std::uint8_t;
+ using timer_register_type = std::uint8_t;
// Do the first read of the timer0 counter and the system tick.
- const timer_register_type tim0_cnt_1 = mcal::reg::reg_access_static::reg_get();
- const mcal::gpt::value_type sys_tick_1 = mcal_gpt_system_tick;
+ const auto t0_cnt_1 = mcal::reg::reg_access_static::reg_get();
+ const auto sys_tick_1 = mcal_gpt_system_tick;
// Do the second read of the timer0 counter.
- const timer_register_type tim0_cnt_2 = mcal::reg::reg_access_static::reg_get();
+ const auto t0_cnt_2 = mcal::reg::reg_access_static::reg_get();
- // Perform the consistency check.
- const mcal::gpt::value_type consistent_microsecond_tick =
- ((tim0_cnt_2 >= tim0_cnt_1) ? mcal::gpt::value_type(sys_tick_1 | std::uint8_t(tim0_cnt_1 >> 1U))
- : mcal::gpt::value_type(mcal_gpt_system_tick | std::uint8_t(tim0_cnt_2 >> 1U)));
+ const auto t0_tick_is_consistent = (t0_cnt_2 >= t0_cnt_1);
- return consistent_microsecond_tick;
+ // Perform the consistency check.
+ const auto consistent_half_microsecond_tick =
+ static_cast
+ (
+ t0_tick_is_consistent ? static_cast(sys_tick_1 | t0_cnt_1)
+ : static_cast(mcal_gpt_system_tick | t0_cnt_2)
+ );
+
+ // Scale the timer0 tick to 1MHz and perform a rounding correction.
+ return
+ static_cast
+ (
+ static_cast
+ (
+ static_cast
+ (
+ static_cast(consistent_half_microsecond_tick)
+ + static_cast(UINT8_C(1))
+ )
+ / static_cast(UINT8_C(2))
+ )
+ );
}
else
{
- return mcal::gpt::value_type(0U);
+ return static_cast(UINT8_C(0));
}
}
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_gpt.h b/examples/chapter09_08a/src/mcal/avr/mcal_gpt.h
index d94491117..ce3a093e4 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_gpt.h
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_gpt.h
@@ -1,45 +1,29 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
//
-#ifndef MCAL_GPT_2011_10_20_H_
- #define MCAL_GPT_2011_10_20_H_
+#ifndef MCAL_GPT_2011_10_20_H
+ #define MCAL_GPT_2011_10_20_H
- #include
#include
- #include
-
- // Forward declaration of the util::timer template class.
- namespace util
- {
- template
- class timer;
- }
-
namespace mcal
{
namespace gpt
{
- typedef void config_type;
- typedef std::uint64_t value_type;
+ using config_type = void;
+ using value_type = std::uint64_t;
- void init(const config_type*);
+ auto init(const config_type*) -> void;
struct secure final
{
- private:
- static value_type get_time_elapsed();
-
- friend std::chrono::high_resolution_clock::time_point std::chrono::high_resolution_clock::now() noexcept;
-
- template
- friend class util::timer;
+ static auto get_time_elapsed() -> value_type;
};
}
}
-#endif // MCAL_GPT_2011_10_20_H_
+#endif // MCAL_GPT_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_led.cpp b/examples/chapter09_08a/src/mcal/avr/mcal_led.cpp
index e378682d5..c9971f653 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_led.cpp
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_led.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2020.
+// 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)
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_led.h b/examples/chapter09_08a/src/mcal/avr/mcal_led.h
index 7dc79b163..c91fe8413 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_led.h
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_led.h
@@ -1,12 +1,12 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2020.
+// 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)
//
-#ifndef MCAL_LED_2010_09_14_H_
- #define MCAL_LED_2010_09_14_H_
+#ifndef MCAL_LED_2010_09_14_H
+ #define MCAL_LED_2010_09_14_H
#include
@@ -18,4 +18,4 @@
}
}
-#endif // MCAL_LED_2010_09_14_H_
+#endif // MCAL_LED_2010_09_14_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_port.h b/examples/chapter09_08a/src/mcal/avr/mcal_port.h
index fbe2a2bd2..6676e1eb3 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_port.h
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_port.h
@@ -10,6 +10,15 @@
#include
+ #include
+
+ auto mcal_port_pin_expander_set_direction_output(const uint8_t bpos) -> void;
+ auto mcal_port_pin_expander_set_direction_input (const uint8_t bpos) -> void;
+ auto mcal_port_pin_expander_set_pin_high (const uint8_t bpos) -> void;
+ auto mcal_port_pin_expander_set_pin_low (const uint8_t bpos) -> void;
+ auto mcal_port_pin_expander_read_input_value (const uint8_t bpos) -> bool;
+ auto mcal_port_pin_expander_toggle_pin (const uint8_t bpos) -> void;
+
namespace mcal
{
namespace port
@@ -97,6 +106,18 @@
bpos_value>::bit_not();
}
};
+
+ template
+ class port_pin_expander
+ {
+ public:
+ static auto set_direction_output() -> void { mcal_port_pin_expander_set_direction_output(bpos); }
+ static auto set_direction_input () -> void { mcal_port_pin_expander_set_direction_input (bpos); }
+ static auto set_pin_high () -> void { mcal_port_pin_expander_set_pin_high (bpos); }
+ static auto set_pin_low () -> void { mcal_port_pin_expander_set_pin_low (bpos); }
+ static auto read_input_value () -> bool { return mcal_port_pin_expander_read_input_value (bpos); }
+ static auto toggle_pin () -> void { mcal_port_pin_expander_toggle_pin (bpos); }
+ };
}
}
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_pwm.cpp b/examples/chapter09_08a/src/mcal/avr/mcal_pwm.cpp
index d49165912..0e08f3ef1 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_pwm.cpp
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_pwm.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// Copyright Christopher Kormanyos 2007 - 2024.
// 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)
@@ -7,6 +7,6 @@
#include
-void mcal::pwm::init(const mcal::pwm::config_type*)
+auto mcal::pwm::init(const mcal::pwm::config_type*) -> void
{
}
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_pwm.h b/examples/chapter09_08a/src/mcal/avr/mcal_pwm.h
index 1fe9536e3..1ced6476a 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_pwm.h
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_pwm.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// Copyright Christopher Kormanyos 2007 - 2024.
// 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)
@@ -14,7 +14,7 @@
{
using config_type = void;
- void init(const config_type*);
+ auto init(const config_type*) -> void;
}
}
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_ser.h b/examples/chapter09_08a/src/mcal/avr/mcal_ser.h
new file mode 100644
index 000000000..bdcb95ad9
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_ser.h
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2024.
+// 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)
+//
+
+#ifndef MCAL_SER_2011_10_20_H
+ #define MCAL_SER_2011_10_20_H
+
+ namespace mcal
+ {
+ namespace ser
+ {
+ using config_type = void;
+
+ inline auto init(const config_type*) -> void { }
+ }
+ }
+
+#endif // MCAL_SER_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_spi.cpp b/examples/chapter09_08a/src/mcal/avr/mcal_spi.cpp
new file mode 100644
index 000000000..cf6952d71
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_spi.cpp
@@ -0,0 +1,12 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2012 - 2024.
+// 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
+
+auto mcal::spi::init(const config_type*) -> void
+{
+}
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_spi.h b/examples/chapter09_08a/src/mcal/avr/mcal_spi.h
new file mode 100644
index 000000000..81790dbd3
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_spi.h
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2012 - 2024.
+// 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)
+//
+
+#ifndef MCAL_SPI_2012_05_24_H
+ #define MCAL_SPI_2012_05_24_H
+
+ namespace mcal { namespace spi {
+
+ using config_type = void;
+
+ auto init(const config_type*) -> void;
+
+ } }
+
+#endif // MCAL_SPI_2012_05_24_H
diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_wdg.h b/examples/chapter09_08a/src/mcal/avr/mcal_wdg.h
index 8e8141310..94949ac58 100644
--- a/examples/chapter09_08a/src/mcal/avr/mcal_wdg.h
+++ b/examples/chapter09_08a/src/mcal/avr/mcal_wdg.h
@@ -8,10 +8,6 @@
#ifndef MCAL_WDT_2010_04_10_H
#define MCAL_WDT_2010_04_10_H
- extern "C" void __my_startup() __attribute__((section(".startup"), used, noinline));
-
- namespace sys { namespace idle { auto task_func() -> void; } }
-
namespace mcal
{
namespace wdg
@@ -22,11 +18,7 @@
struct secure final
{
- private:
static auto trigger() -> void;
-
- friend auto ::sys::idle::task_func() -> void;
- friend auto ::__my_startup() -> void;
};
}
}
diff --git a/examples/chapter09_08a/src/mcal/mcal.cpp b/examples/chapter09_08a/src/mcal/mcal.cpp
index 06c77cb46..985f7f0d9 100644
--- a/examples/chapter09_08a/src/mcal/mcal.cpp
+++ b/examples/chapter09_08a/src/mcal/mcal.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2019.
+// 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)
@@ -7,7 +7,7 @@
#include
-void mcal::init()
+auto mcal::init() -> void
{
// Initialize the microcontroller abstraction layer.
@@ -20,6 +20,10 @@ void mcal::init()
mcal::irq::init(nullptr);
mcal::gpt::init(nullptr);
+ mcal::ser::init(nullptr);
+ mcal::spi::init(nullptr);
+ mcal::pwm::init(nullptr);
+ mcal::eep::init(nullptr);
mcal::cpu::post_init();
}
diff --git a/examples/chapter09_08a/src/mcal/mcal.h b/examples/chapter09_08a/src/mcal/mcal.h
index 7676cfed7..ba0967737 100644
--- a/examples/chapter09_08a/src/mcal/mcal.h
+++ b/examples/chapter09_08a/src/mcal/mcal.h
@@ -1,27 +1,35 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2018.
+// 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)
//
-#ifndef MCAL_2011_10_20_H_
- #define MCAL_2011_10_20_H_
+#ifndef MCAL_2011_10_20_H
+ #define MCAL_2011_10_20_H
#include
+ #include
#include
#include
- #include
+ #include
+ #include
+ #include
+ #include
+ #include
#include
- static_assert( (std::numeric_limits::digits >= 32)
- && (std::numeric_limits::is_integer == true)
- && (std::numeric_limits::is_signed == false),
- "The gpt value type must be an unsigned integer type having at least 32 bits");
+ #include
+ #include
+
+ static_assert( (std::numeric_limits::digits >= static_cast(INT8_C(64)))
+ && std::numeric_limits::is_integer
+ && (!std::numeric_limits::is_signed),
+ "The gpt value type must be an unsigned integer type having at least 64 bits.");
namespace mcal
{
- void init();
- }
+ auto init() -> void;
+ } // namespace mcal
-#endif // MCAL_2011_10_20_H_
+#endif // MCAL_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion_with_stdlib.cpp b/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion_with_stdlib.cpp
new file mode 100644
index 000000000..f46214b34
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion_with_stdlib.cpp
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2021.
+// 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
+
+extern "C"
+{
+ // Patched functions.
+ void __cxa_pure_virtual ();
+ char* __cxa_demangle (const char*, char*, size_t*, int*);
+
+ void __cxa_pure_virtual () { }
+ char* __cxa_demangle (const char*, char*, size_t*, int*) { return nullptr; }
+}
+
+extern "C"
+{
+ // Patched labels.
+ void* __dso_handle;
+}
diff --git a/examples/chapter09_08a/src/mcal/mcal_gpt_arm_sys_tick.h b/examples/chapter09_08a/src/mcal/mcal_gpt_arm_sys_tick.h
new file mode 100644
index 000000000..65620803d
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/mcal_gpt_arm_sys_tick.h
@@ -0,0 +1,181 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2022 - 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)
+//
+
+#ifndef MCAL_GPT_ARM_SYS_TICK_2022_11_30_H
+ #define MCAL_GPT_ARM_SYS_TICK_2022_11_30_H
+
+ #include
+ #include
+ #include
+
+ #if defined(__GNUC__)
+ extern "C" auto __sys_tick_handler() -> void __attribute__((used, noinline));
+ #endif
+
+ namespace mcal { namespace gpt {
+
+ template
+ class arm_sys_tick_base
+ {
+ protected:
+ using register_address_type = RegisterAddressType;
+ using register_value_type = RegisterValueType;
+ using value_type = ValueType;
+
+ static constexpr auto scs_base = static_cast(UINT32_C(0xE000E000));
+ static constexpr auto sys_tick_mhz = SysTickMHz;
+ static constexpr auto sys_tick_base = static_cast(scs_base + static_cast(UINT8_C(0x10)));
+ static constexpr auto sys_tick_ctrl = static_cast(sys_tick_base + static_cast(UINT8_C(0x00)));
+ static constexpr auto sys_tick_load = static_cast(sys_tick_base + static_cast(UINT8_C(0x04)));
+ static constexpr auto sys_tick_val = static_cast(sys_tick_base + static_cast(UINT8_C(0x08)));
+ static constexpr auto sys_tick_cal = static_cast(sys_tick_base + static_cast(UINT8_C(0x0C)));
+
+ template(UINT8_C(0))>
+ struct reg_access_static
+ {
+ static auto reg_get() noexcept -> register_value_type { volatile register_value_type* pa = reinterpret_cast(address); return *pa; }
+ static auto reg_set() noexcept -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = value; }
+ static auto reg_or () noexcept -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = *pa | value; }
+ };
+ };
+
+ template
+ class arm_sys_tick : private arm_sys_tick_base
+ {
+ private:
+ using base_class_type = arm_sys_tick_base;
+
+ using register_address_type = typename base_class_type::register_address_type;
+ using register_value_type = typename base_class_type::register_value_type;
+
+ static_assert(std::numeric_limits::digits == static_cast(INT8_C(32)),
+ "Error: Wrong width of register address type");
+
+ static_assert(std::numeric_limits::digits == static_cast(INT8_C(32)),
+ "Error: Wrong width of register value type");
+
+ public:
+ using value_type = typename base_class_type::value_type;
+
+ static constexpr auto sys_tick_mhz() noexcept -> std::uint32_t { return SysTickMHz; }
+
+ static auto init() noexcept -> void
+ {
+ if(!my_is_init)
+ {
+ my_is_init = true;
+
+ // Set up an interrupt on the ARM(R) sys-tick.
+
+ base_class_type::template reg_access_static(UINT8_C(0))>::reg_set();
+
+ // Set the sys-tick reload register.
+ base_class_type::template reg_access_static(UINT32_C(0x00FFFFFF))>::reg_set();
+
+ // Initialize the sys-tick counter value.
+ base_class_type::template reg_access_static(UINT8_C(0))>::reg_set();
+
+ // Set the sys-tick clock source to be the processor clock.
+ base_class_type::template reg_access_static(UINT8_C(4))>::reg_or();
+
+ // Enable the sys-tick interrupt.
+ base_class_type::template reg_access_static(UINT8_C(2))>::reg_or();
+
+ // Enable the sys-tick timer.
+ base_class_type::template reg_access_static(UINT8_C(1))>::reg_or();
+ }
+ }
+
+ static auto get_time_elapsed() noexcept -> value_type
+ {
+ return
+ static_cast
+ (
+ my_is_init ? get_consistent_microsecond_tick() : static_cast(UINT8_C(0))
+ );
+ }
+
+ private:
+ static volatile value_type my_sys_tick_value;
+ static bool my_is_init;
+
+ static auto get_consistent_microsecond_tick() noexcept -> value_type
+ {
+ // Return the system tick using a multiple read to ensure data consistency.
+
+ // Do the first read of the sys-tick counter and the sys-tick
+ // value. Also handle reverse counting for the sys-tick counter,
+ // since this timer counts down.
+
+ const auto sys_tick_counter_1 =
+ static_cast
+ (
+ static_cast
+ (
+ static_cast(UINT32_C(0x00FFFFFF))
+ - static_cast(base_class_type::template reg_access_static::reg_get())
+ )
+ );
+
+ const value_type sys_tick_value { my_sys_tick_value };
+
+ // Do the second read of the sys-tick counter and the sys-tick
+ // value. Also handle reverse counting for the sys-tick counter,
+ // since this timer counts down.
+
+ const auto sys_tick_counter_2 =
+ static_cast
+ (
+ static_cast
+ (
+ static_cast(UINT32_C(0x00FFFFFF))
+ - static_cast(base_class_type::template reg_access_static::reg_get())
+ )
+ );
+
+ // Perform the consistency check.
+
+ const std::uint64_t
+ sys_tick_consistent_value
+ {
+ static_cast
+ (
+ ((sys_tick_counter_2 >= sys_tick_counter_1)
+ ? static_cast(static_cast( sys_tick_value) | sys_tick_counter_1)
+ : static_cast(static_cast(my_sys_tick_value) | sys_tick_counter_2))
+ )
+ };
+
+ // Perform scaling and include a rounding correction.
+ return
+ static_cast
+ (
+ static_cast
+ (
+ sys_tick_consistent_value
+ + static_cast(base_class_type::sys_tick_mhz / static_cast(UINT8_C(2)))
+ )
+ / base_class_type::sys_tick_mhz
+ );
+ }
+
+ #if defined(__GNUC__)
+ friend auto ::__sys_tick_handler() -> void;
+ #endif
+ };
+
+ template bool arm_sys_tick::my_is_init;
+ template volatile typename arm_sys_tick::value_type arm_sys_tick::my_sys_tick_value;
+
+ } }
+
+#endif // MCAL_GPT_ARM_SYS_TICK_2022_11_30_H
diff --git a/examples/chapter09_08a/src/mcal/mcal_helper.h b/examples/chapter09_08a/src/mcal/mcal_helper.h
new file mode 100644
index 000000000..44b4b9d50
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/mcal_helper.h
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 2024.
+// 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)
+//
+
+#ifndef MCAL_HELPER_2020_05_21_H
+ #define MCAL_HELPER_2020_05_21_H
+
+ #include
+ #include
+
+ #include
+ #include
+
+ namespace mcal { namespace helper {
+
+ template
+ auto nop_maker() -> typename std::enable_if<(1U < nop_count) && (nop_count <= 12U), void>::type
+ {
+ nop_maker();
+
+ mcal::cpu::nop();
+ }
+
+ template
+ auto nop_maker() -> typename std::enable_if<(nop_count == 1U), void>::type
+ {
+ mcal::cpu::nop();
+ }
+
+ template
+ auto nop_maker() -> typename std::enable_if<(nop_count == 0U), void>::type
+ {
+ }
+
+ template
+ auto nop_maker() -> typename std::enable_if<(12U < nop_count), void>::type
+ {
+ for(std::uint_fast16_t i = 0U; i < nop_count; ++i)
+ {
+ mcal::cpu::nop();
+ }
+ }
+
+ template
+ auto disable_all_interrupts(const bool = has_disable_enable_interrupts,
+ const typename std::enable_if::type* = nullptr) noexcept -> void
+ {
+ mcal::irq::disable_all();
+ }
+
+ template
+ auto enable_all_interrupts(const bool = has_disable_enable_interrupts,
+ const typename std::enable_if::type* = nullptr) noexcept -> void
+ {
+ mcal::irq::enable_all();
+ }
+
+ template
+ auto disable_all_interrupts(const bool = has_disable_enable_interrupts,
+ const typename std::enable_if<(!has_disable_enable_interrupts)>::type* = nullptr) noexcept -> void { }
+
+ template
+ auto enable_all_interrupts(const bool = has_disable_enable_interrupts,
+ const typename std::enable_if<(!has_disable_enable_interrupts)>::type* = nullptr) noexcept -> void { }
+
+ } } // namespace mcal::helper
+
+#endif // MCAL_HELPER_2020_05_21_H
diff --git a/examples/chapter09_08a/src/mcal/mcal_reg_access_dynamic.h b/examples/chapter09_08a/src/mcal/mcal_reg_access_dynamic.h
index dd121cff7..3bc3cf54b 100644
--- a/examples/chapter09_08a/src/mcal/mcal_reg_access_dynamic.h
+++ b/examples/chapter09_08a/src/mcal/mcal_reg_access_dynamic.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2013 - 2025.
+// Copyright Christopher Kormanyos 2013 - 2024.
// 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)
diff --git a/examples/chapter09_08a/src/mcal/mcal_reg_access_static.h b/examples/chapter09_08a/src/mcal/mcal_reg_access_static.h
index a444f183f..564c3dc2f 100644
--- a/examples/chapter09_08a/src/mcal/mcal_reg_access_static.h
+++ b/examples/chapter09_08a/src/mcal/mcal_reg_access_static.h
@@ -1,5 +1,5 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2025.
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2024.
// 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)
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_benchmark.h b/examples/chapter09_08a/src/mcal/win32/mcal_benchmark.h
new file mode 100644
index 000000000..4795ccb6d
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_benchmark.h
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2014 - 2023.
+// 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)
+//
+
+#ifndef MCAL_BENCHMARK_2014_04_16_H
+ #define MCAL_BENCHMARK_2014_04_16_H
+
+ #include
+
+ namespace mcal
+ {
+ namespace benchmark
+ {
+ using benchmark_port_type = mcal::port::port_pin;
+ } // namespace benchmark
+ } // namespace mcal
+
+#endif // MCAL_BENCHMARK_2014_04_16_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_cpu.h b/examples/chapter09_08a/src/mcal/win32/mcal_cpu.h
index 9b180093b..62dfd643b 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_cpu.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_cpu.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -13,14 +13,18 @@
#include
#include
- namespace mcal { namespace cpu {
+ namespace mcal
+ {
+ namespace cpu
+ {
- auto init() -> void;
+ auto init() -> void;
- inline auto post_init() -> void { }
+ inline auto post_init() -> void { }
- inline auto nop() -> void { }
+ inline auto nop() -> void { }
- } } // namespace mcal::cpu
+ } // namespace cpu
+ } // namespace mcal
#endif // MCAL_CPU_2009_02_14_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_eep.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_eep.cpp
new file mode 100644
index 000000000..2c7c06b8b
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_eep.cpp
@@ -0,0 +1,14 @@
+#include
+
+auto mcal::eep::write(const address_type addr, const std::uint8_t data) -> void // NOLINT(bugprone-easily-swappable-parameters)
+{
+ static_cast(addr);
+ static_cast(data);
+}
+
+auto mcal::eep::read(const address_type addr) -> std::uint8_t
+{
+ static_cast(addr);
+
+ return static_cast(UINT8_C(0));
+}
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_eep.h b/examples/chapter09_08a/src/mcal/win32/mcal_eep.h
new file mode 100644
index 000000000..3e7d03690
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_eep.h
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2022.
+// 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)
+//
+
+#ifndef MCAL_EEP_2018_12_15_H
+ #define MCAL_EEP_2018_12_15_H
+
+ #include
+
+ namespace mcal
+ {
+ namespace eep
+ {
+ using config_type = void;
+ using address_type = std::uint64_t;
+
+ inline auto init(const config_type*) -> void { }
+
+ auto write(const address_type addr, const std::uint8_t data) -> void;
+ auto read (const address_type addr) -> std::uint8_t;
+ } // namespace eep
+ } // namespace mcal
+
+#endif // MCAL_EEP_2018_12_15_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_gpt.h b/examples/chapter09_08a/src/mcal/win32/mcal_gpt.h
index 676143e52..e1a6ee00e 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_gpt.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_gpt.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -8,18 +8,8 @@
#ifndef MCAL_GPT_2011_10_20_H
#define MCAL_GPT_2011_10_20_H
- #include
#include
- #include
-
- // Forward declaration of the util::timer template class.
- namespace util
- {
- template
- class timer;
- }
-
namespace mcal
{
namespace gpt
@@ -29,16 +19,11 @@
inline auto init(const config_type*) noexcept -> void { }
- class secure final
+ struct secure final
{
static auto get_time_elapsed() -> value_type;
-
- friend std::chrono::high_resolution_clock::time_point std::chrono::high_resolution_clock::now() UTIL_NOEXCEPT;
-
- template
- friend class util::timer;
};
- }
- }
+ } // namespace gpt
+ } // namespace mcal
#endif // MCAL_GPT_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_irq.h b/examples/chapter09_08a/src/mcal/win32/mcal_irq.h
index ba9ca8fd9..0eee5f010 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_irq.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_irq.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -16,9 +16,9 @@
auto init(const config_type*) -> void;
- inline auto enable_all () -> void { }
- inline auto disable_all() -> void { }
- }
- }
+ inline auto enable_all () noexcept -> void { }
+ inline auto disable_all() noexcept -> void { }
+ } // namespace irq
+ } // namespace mcal
#endif // MCAL_IRQ_2010_04_10_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_led.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_led.cpp
index 540486992..ec071272a 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_led.cpp
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_led.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2020.
+// 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)
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_led.h b/examples/chapter09_08a/src/mcal/win32/mcal_led.h
index eb3311015..1897eb522 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_led.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_led.h
@@ -15,7 +15,7 @@
namespace led
{
auto led0() -> led_base&;
- }
- }
+ } // namespace led
+ } // namespace mcal
#endif // MCAL_LED_2010_09_14_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_osc.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_osc.cpp
new file mode 100644
index 000000000..79036e733
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_osc.cpp
@@ -0,0 +1,13 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2020.
+// 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
+
+auto mcal::osc::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter)
+{
+ // Subroutine is empty on purpose.
+}
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_osc.h b/examples/chapter09_08a/src/mcal/win32/mcal_osc.h
new file mode 100644
index 000000000..603503bab
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_osc.h
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2020.
+// 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)
+//
+
+#ifndef MCAL_OSC_2011_10_20_H
+ #define MCAL_OSC_2011_10_20_H
+
+ namespace mcal
+ {
+ namespace osc
+ {
+ using config_type = void;
+
+ auto init(const config_type*) -> void;
+ } // namespace osc
+ } // namespace mcal
+
+#endif // MCAL_OSC_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_port.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_port.cpp
new file mode 100644
index 000000000..7d5c0e23a
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_port.cpp
@@ -0,0 +1,13 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2018.
+// 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
+
+auto mcal::port::init(const config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter)
+{
+ // Subroutine is empty on purpose.
+}
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_port.h b/examples/chapter09_08a/src/mcal/win32/mcal_port.h
index 43447f387..bae7087fd 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_port.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_port.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -19,14 +19,14 @@
class port_pin
{
public:
- static auto set_direction_output()noexcept -> void { }
- static auto set_direction_input ()noexcept -> void { }
- static auto set_pin_high ()noexcept -> void { }
- static auto set_pin_low ()noexcept -> void { }
- static auto read_input_value ()noexcept -> bool { return false; }
- static auto toggle_pin ()noexcept -> void { }
+ static constexpr auto set_direction_output() noexcept -> void { }
+ static constexpr auto set_direction_input () noexcept -> void { }
+ static constexpr auto set_pin_high () noexcept -> void { }
+ static constexpr auto set_pin_low () noexcept -> void { }
+ static constexpr auto read_input_value () noexcept -> bool { return false; }
+ static constexpr auto toggle_pin () noexcept -> void { }
};
- }
- }
+ } // namespace port
+ } // namespace mcal
#endif // MCAL_PORT_2012_06_27_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_pwm.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_pwm.cpp
new file mode 100644
index 000000000..ed11d307b
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_pwm.cpp
@@ -0,0 +1,20 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2020.
+// 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
+#include
+
+auto mcal::pwm::pwm0() noexcept -> mcal::pwm::pwm_base&
+{
+ static mcal::pwm::pwm_console pwm;
+
+ static const volatile bool init_is_ok = pwm.init();
+
+ static_cast(init_is_ok);
+
+ return pwm;
+}
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_pwm.h b/examples/chapter09_08a/src/mcal/win32/mcal_pwm.h
new file mode 100644
index 000000000..40f66189f
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_pwm.h
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+
+#ifndef MCAL_PWM_2010_09_14_H
+ #define MCAL_PWM_2010_09_14_H
+
+ #include
+
+ namespace mcal
+ {
+ namespace pwm
+ {
+ using config_type = void;
+
+ inline auto init(const config_type*) -> void { }
+
+ auto pwm0() noexcept -> mcal::pwm::pwm_base&;
+ } // namespace pwm
+ } // namespace mcal
+
+#endif // MCAL_PWM_2010_09_14_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_ser.h b/examples/chapter09_08a/src/mcal/win32/mcal_ser.h
new file mode 100644
index 000000000..599e71bd5
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_ser.h
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2020.
+// 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)
+//
+
+#ifndef MCAL_SER_2011_10_20_H
+ #define MCAL_SER_2011_10_20_H
+
+ namespace mcal
+ {
+ namespace ser
+ {
+ using config_type = void;
+
+ inline auto init(const config_type*) -> void { }
+ } // namespace ser
+ } // namespace mcal
+
+#endif // MCAL_SER_2011_10_20_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_spi.cpp b/examples/chapter09_08a/src/mcal/win32/mcal_spi.cpp
new file mode 100644
index 000000000..b0f02b30b
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_spi.cpp
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2012 - 2020.
+// 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
+
+#include
+
+auto mcal::spi::init(const mcal::spi::config_type*) -> void // NOLINT(readability-named-parameter,hicpp-named-parameter)
+{
+ // Subroutine is empty on purpose.
+}
+
+auto mcal::spi::spi0() -> util::communication_base&
+{
+ static mcal::spi::spi_software_dummy com0;
+
+ return com0;
+}
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_spi.h b/examples/chapter09_08a/src/mcal/win32/mcal_spi.h
new file mode 100644
index 000000000..c0f26e71b
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_spi.h
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2012 - 2020.
+// 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)
+//
+
+#ifndef MCAL_SPI_2012_05_24_H
+ #define MCAL_SPI_2012_05_24_H
+
+ #include
+
+ namespace mcal
+ {
+ namespace spi
+ {
+
+ using config_type = void;
+
+ auto init(const config_type*) -> void;
+
+ auto spi0() -> util::communication_base&;
+
+ } // namespace spi
+ } // namespace mcal
+
+#endif // MCAL_SPI_2012_05_24_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_wdg.h b/examples/chapter09_08a/src/mcal/win32/mcal_wdg.h
index f0810a9a4..a26e36a84 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_wdg.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_wdg.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2023.
+// 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)
@@ -8,15 +8,6 @@
#ifndef MCAL_WDG_2010_04_10_H
#define MCAL_WDG_2010_04_10_H
- // Forward declaration of the util::timer template class.
- namespace util
- {
- template
- class timer;
- }
-
- namespace sys { namespace idle { void task_func(); } }
-
namespace mcal
{
namespace wdg
@@ -25,16 +16,11 @@
auto init(const config_type*) -> void;
- class secure final
+ struct secure final
{
static auto trigger() -> void;
-
- friend auto ::sys::idle::task_func() -> void;
-
- template
- friend class util::timer;
};
- }
- }
+ } // namespace wdg
+ } // namespace mcal
#endif // MCAL_WDG_2010_04_10_H
diff --git a/examples/chapter09_08a/src/mcal/win32/mcal_wdg_watchdog.h b/examples/chapter09_08a/src/mcal/win32/mcal_wdg_watchdog.h
index 5e5d34767..f6310da5d 100644
--- a/examples/chapter09_08a/src/mcal/win32/mcal_wdg_watchdog.h
+++ b/examples/chapter09_08a/src/mcal/win32/mcal_wdg_watchdog.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2013 - 2023.
+// Copyright Christopher Kormanyos 2013 - 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)
@@ -8,15 +8,16 @@
#ifndef MCAL_WDG_WATCHDOG_2013_12_11_H
#define MCAL_WDG_WATCHDOG_2013_12_11_H
+ #include
+
+ #include
+ #include
+
#include
#include
#include
#include
- #include
- #include
- #include
-
#if defined(_MSC_VER)
#define MCAL_WDG_NORETURN
#else
@@ -69,8 +70,8 @@
timer_type my_timer { my_period };
const std::thread my_thread;
- static watchdog my_watchdog;
- static std::atomic_flag my_lock;
+ static watchdog my_watchdog; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+ static std::atomic_flag my_lock; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
auto get_watchdog_timeout() const -> bool
{
@@ -90,7 +91,7 @@
MCAL_WDG_NORETURN static auto thread_function() -> void
{
- std::this_thread::sleep_for(std::chrono::milliseconds(10U));
+ std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT8_C(10))));
bool timeout_has_occurred = false;
@@ -100,7 +101,7 @@
{
print_timeout_message();
- std::this_thread::sleep_for(std::chrono::milliseconds(500U));
+ std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT16_C(500))));
}
else
{
@@ -109,20 +110,20 @@
timeout_has_occurred = true;
}
- std::this_thread::sleep_for(std::chrono::milliseconds(20U));
+ std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(UINT8_C(20))));
}
}
}
- friend class ::mcal::wdg::secure;
+ friend struct ::mcal::wdg::secure;
};
template
- watchdog watchdog::my_watchdog(thread_function);
+ watchdog watchdog::my_watchdog(thread_function); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables,cert-err58-cpp)
template
- std::atomic_flag watchdog::my_lock = ATOMIC_FLAG_INIT;
- }
- }
+ std::atomic_flag watchdog::my_lock = ATOMIC_FLAG_INIT; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+ } // namespace wdg
+ } // namespace mcal
#endif // MCAL_WDG_WATCHDOG_2013_12_11_H
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_base.h b/examples/chapter09_08a/src/mcal_led/mcal_led_base.h
index e9d099b72..3d24f22f2 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_base.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2013 - 2023.
+// Copyright Christopher Kormanyos 2013 - 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)
@@ -12,12 +12,14 @@
namespace mcal { namespace led {
- class led_base : private util::noncopyable
+ class led_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
{
public:
+ virtual ~led_base() = default;
+
virtual auto toggle() -> void = 0;
- virtual auto state_is_on() const -> bool = 0;
+ virtual auto state_is_on() const noexcept -> bool = 0;
protected:
constexpr led_base() = default;
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_boolean_state_base.h b/examples/chapter09_08a/src/mcal_led/mcal_led_boolean_state_base.h
index e74ed23b2..f0faf337c 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_boolean_state_base.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_boolean_state_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2020 - 2023.
+// Copyright Christopher Kormanyos 2020 - 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)
@@ -12,23 +12,29 @@
namespace mcal { namespace led {
- class led_boolean_state_base : public mcal::led::led_base
+ class led_boolean_state_base : public mcal::led::led_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
{
+ public:
+ ~led_boolean_state_base() override = default;
+
+ auto state_is_on() const noexcept -> bool override { return is_on; }
+
protected:
constexpr led_boolean_state_base() = default;
auto toggle() -> void override
{
// Toggle the LED state.
- is_on = (!is_on);
+ set_is_on(!is_on);
}
- auto state_is_on() const -> bool override { return is_on; }
+ auto set_is_on(const bool val) noexcept -> void { is_on = val; }
private:
bool is_on { };
};
- } } // namespace mcal::led
+ } // namespace led
+ } // namespace mcal
#endif // MCAL_LED_BOOLEAN_STATE_BASE_2020_08_07_H
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_console.h b/examples/chapter09_08a/src/mcal_led/mcal_led_console.h
index 92516cd2e..8c15b5bba 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_console.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_console.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2013 - 2023.
+// Copyright Christopher Kormanyos 2013 - 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)
@@ -8,37 +8,54 @@
#ifndef MCAL_LED_CONSOLE_2020_04_23_H
#define MCAL_LED_CONSOLE_2020_04_23_H
+ #include
+
+ #include
#include
#include
-
- #include
+ #include
namespace mcal { namespace led {
- class led_console final : public mcal::led::led_boolean_state_base
+ class led_console final : public mcal::led::led_boolean_state_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
{
public:
- explicit constexpr led_console(const std::uint_fast8_t i)
- : my_index(i) { }
+ explicit constexpr led_console(const std::uint_fast8_t idx = std::uint_fast8_t { UINT8_C(0) }) noexcept
+ : my_index(idx) { }
+
+ ~led_console() override = default;
auto toggle() -> void override
{
using base_class_type = mcal::led::led_boolean_state_base;
- // Print the LED state.
- std::cout << "LED"
- << static_cast(my_index)
- << " is "
- << (base_class_type::state_is_on() ? "on" : "off")
- << std::endl;
-
base_class_type::toggle();
+
+ // Print the LED state to the console.
+ std::stringstream strm { };
+
+ strm << "LED"
+ << static_cast(my_index)
+ << " is "
+ << (base_class_type::state_is_on() ? "on" : "off");
+
+ while(console_sync().test_and_set(std::memory_order_acquire)) { }
+ std::cout << strm.str() << std::endl;
+ console_sync().clear(std::memory_order_release);
}
private:
- const std::uint_fast8_t my_index;
+ const std::uint_fast8_t my_index { };
+
+ static auto console_sync() noexcept -> std::atomic_flag&
+ {
+ static std::atomic_flag console_lock { };
+
+ return console_lock;
+ }
};
- } } // namespace mcal::led
+ } // namespace led
+ } // namespace mcal
#endif // MCAL_LED_CONSOLE_2020_04_23_H
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_dummy.h b/examples/chapter09_08a/src/mcal_led/mcal_led_dummy.h
new file mode 100644
index 000000000..ea451ac5b
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_dummy.h
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 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)
+//
+
+#ifndef MCAL_LED_DUMMY_2025_02_22_H
+ #define MCAL_LED_DUMMY_2025_02_22_H
+
+ #include
+ #include
+
+ namespace mcal { namespace led {
+
+ class led_dummy : public mcal::led::led_boolean_state_base
+ {
+ public:
+ led_dummy() noexcept
+ {
+ }
+
+ ~led_dummy() override = default;
+
+ auto toggle() noexcept -> void override
+ {
+ using base_class_type = mcal::led::led_boolean_state_base;
+
+ base_class_type::toggle();
+ }
+ };
+
+ } // namespace led
+ } // namespace mcal
+
+#endif // MCAL_LED_DUMMY_2025_02_22_H
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_port.h b/examples/chapter09_08a/src/mcal_led/mcal_led_port.h
index f0d383ef7..4157ec58c 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_port.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_port.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2013 - 2023.
+// Copyright Christopher Kormanyos 2013 - 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)
@@ -17,13 +17,15 @@
class led_port : public mcal::led::led_boolean_state_base
{
public:
- led_port()
+ led_port() noexcept
{
port_type::set_pin_low();
port_type::set_direction_output();
}
- auto toggle() -> void override
+ ~led_port() override = default;
+
+ auto toggle() noexcept -> void override
{
using base_class_type = led_boolean_state_base;
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_port_inverted.h b/examples/chapter09_08a/src/mcal_led/mcal_led_port_inverted.h
index 847661fad..95daaf686 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_port_inverted.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_port_inverted.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2020 - 2023.
+// Copyright Christopher Kormanyos 2020 - 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)
@@ -17,13 +17,15 @@
class led_port_inverted : public mcal::led::led_boolean_state_base
{
public:
- led_port_inverted()
+ led_port_inverted() noexcept
{
port_type::set_pin_high();
port_type::set_direction_output();
}
- auto toggle() -> void override
+ ~led_port_inverted() override = default;
+
+ auto toggle() noexcept -> void override
{
using base_class_type = led_boolean_state_base;
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_pwm.h b/examples/chapter09_08a/src/mcal_led/mcal_led_pwm.h
new file mode 100644
index 000000000..711699092
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_pwm.h
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2013 - 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)
+//
+
+#ifndef MCAL_LED_PWM_2020_04_23_H
+ #define MCAL_LED_PWM_2020_04_23_H
+
+ #include
+ #include
+
+ namespace mcal { namespace led {
+
+ class led_pwm : public mcal::led::led_base
+ {
+ public:
+ explicit led_pwm(mcal::pwm::pwm_base& pwm) : my_pwm(pwm)
+ {
+ my_pwm.set_duty(mcal::pwm::pwm_base::duty_type { UINT8_C(0) });
+ }
+
+ ~led_pwm() override = default;
+
+ auto state_is_on() const noexcept -> bool override { return (my_pwm.get_duty() > static_cast(UINT8_C(0))); }
+
+ auto toggle() -> void override
+ {
+ // Toggle the duty cycle.
+ const auto new_duty =
+ static_cast
+ (
+ state_is_on() ? UINT16_C(0) : UINT16_C(1000)
+ );
+
+ my_pwm.set_duty(new_duty);
+ }
+
+ private:
+ mcal::pwm::pwm_base& my_pwm;
+ };
+
+ } // namespace led
+ } // namespace mcal
+
+#endif // MCAL_LED_PWM_2020_04_23_H
diff --git a/examples/chapter09_08a/src/mcal_led/mcal_led_rgb_base.h b/examples/chapter09_08a/src/mcal_led/mcal_led_rgb_base.h
index 6277b28b8..35655b33e 100644
--- a/examples/chapter09_08a/src/mcal_led/mcal_led_rgb_base.h
+++ b/examples/chapter09_08a/src/mcal_led/mcal_led_rgb_base.h
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2017 - 2023.
+// Copyright Christopher Kormanyos 2017 - 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)
@@ -8,16 +8,18 @@
#ifndef MCAL_LED_RGB_BASE_2023_07_12_H
#define MCAL_LED_RGB_BASE_2023_07_12_H
- #include
-
#include
+ #include
+
namespace mcal { namespace led {
class led_rgb_base : public mcal::led::led_boolean_state_base
{
public:
- auto toggle() -> void override
+ ~led_rgb_base() override = default;
+
+ auto toggle() noexcept -> void override
{
using base_class_type = mcal::led::led_boolean_state_base;
@@ -48,7 +50,7 @@
);
}
- constexpr auto get_color() const noexcept -> std::uint32_t
+ auto get_color() const noexcept -> std::uint32_t
{
return
static_cast
@@ -59,9 +61,9 @@
);
}
- constexpr auto get_hue_r() const noexcept -> std::uint_fast8_t { return my_hue_r; }
- constexpr auto get_hue_g() const noexcept -> std::uint_fast8_t { return my_hue_g; }
- constexpr auto get_hue_b() const noexcept -> std::uint_fast8_t { return my_hue_b; }
+ auto get_hue_r() const noexcept -> std::uint_fast8_t { return my_hue_r; }
+ auto get_hue_g() const noexcept -> std::uint_fast8_t { return my_hue_g; }
+ auto get_hue_b() const noexcept -> std::uint_fast8_t { return my_hue_b; }
protected:
constexpr led_rgb_base() = default;
@@ -94,6 +96,7 @@
}
};
- } } // namespace mcal::led
+ } // namespace led
+ } // namespace mcal
#endif // MCAL_LED_RGB_BASE_2023_07_12_H
diff --git a/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_base.h b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_base.h
new file mode 100644
index 000000000..66f27f3a8
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_base.h
@@ -0,0 +1,41 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 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)
+//
+
+#ifndef MCAL_PWM_BASE_2020_04_12_H
+ #define MCAL_PWM_BASE_2020_04_12_H
+
+ #include
+
+ #include
+
+ namespace mcal { namespace pwm {
+
+ class pwm_base : private util::noncopyable // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+ {
+ public:
+ using duty_type = std::uint16_t;
+
+ virtual ~pwm_base() noexcept = default;
+
+ virtual auto init() noexcept -> bool = 0;
+
+ virtual auto set_duty(const duty_type duty_cycle) -> void { my_duty_cycle = duty_cycle; }
+
+ auto get_duty() const noexcept -> duty_type { return my_duty_cycle; }
+
+ protected:
+ explicit pwm_base(const duty_type initial_duty = static_cast(UINT8_C(0))) noexcept
+ : my_duty_cycle(initial_duty) { }
+
+ private:
+ duty_type my_duty_cycle { }; // NOLINT(readability-identifier-naming)
+ };
+
+ } // namespace pwm
+ } // namespace mcal
+
+#endif // MCAL_PWM_BASE_2020_04_12_H
diff --git a/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_console.h b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_console.h
new file mode 100644
index 000000000..9d19e3dc1
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_console.h
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 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)
+//
+
+#ifndef MCAL_PWM_CONSOLE_2020_04_12_H
+ #define MCAL_PWM_CONSOLE_2020_04_12_H
+
+ #include
+
+ #include
+ #include
+ #include
+
+ namespace mcal { namespace pwm {
+
+ class pwm_console : public mcal::pwm::pwm_base // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+ {
+ private:
+ using base_class_type = mcal::pwm::pwm_base;
+
+ public:
+ pwm_console() = default;
+
+ auto init() noexcept -> bool override { return true; }
+
+ auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override
+ {
+ base_class_type::set_duty(duty_cycle);
+
+ const auto duty_cycle_as_percent =
+ static_cast
+ (
+ static_cast(base_class_type::get_duty()) / 10.0F
+ );
+
+ std::stringstream strm;
+
+ strm << "duty cycle: "
+ << std::fixed
+ << std::setprecision(1)
+ << duty_cycle_as_percent
+ << "%";
+
+ std::cout << strm.str() + (std::string(2U, ' ') + "\r");
+ }
+
+ ~pwm_console() override = default;
+ };
+
+ } // namespace pwm
+ } // namespace mcal
+
+#endif // MCAL_PWM_CONSOLE_2020_04_12_H
diff --git a/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_dummy.h b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_dummy.h
new file mode 100644
index 000000000..2a37fa113
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_dummy.h
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 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)
+//
+
+#ifndef MCAL_PWM_DUMMY_2020_04_29_H
+ #define MCAL_PWM_DUMMY_2020_04_29_H
+
+ #include
+
+ namespace mcal { namespace pwm {
+
+ class pwm_dummy : public mcal::pwm::pwm_base
+ {
+ private:
+ using base_class_type = mcal::pwm::pwm_base;
+
+ public:
+ pwm_dummy() = default;
+
+ auto init() noexcept -> bool override { return true; }
+
+ auto set_duty(const std::uint16_t duty_cycle) noexcept -> void override
+ {
+ base_class_type::set_duty(duty_cycle);
+ }
+
+ ~pwm_dummy() override = default;
+ };
+
+ } // namespace pwm
+ } // namespace mcal
+
+#endif // MCAL_PWM_DUMMY_2020_04_29_H
diff --git a/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_port.h b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_port.h
new file mode 100644
index 000000000..7b454062e
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_pwm/mcal_pwm_port.h
@@ -0,0 +1,78 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+
+#ifndef MCAL_PWM_PORT_2023_08_23_H
+ #define MCAL_PWM_PORT_2023_08_23_H
+
+ #include
+
+ #include
+
+ namespace mcal { namespace pwm {
+
+ // A software PWM template for a port-pin having the standard
+ // port interface for ref_app. The default resolution is 100 ticks.
+
+ template
+ class pwm_port : public pwm_base
+ {
+ private:
+ using base_class_type = pwm_base;
+ using port_pin_type = PortPinType;
+
+ public:
+ using base_class_type::duty_type;
+
+ explicit pwm_port(const duty_type initial_duty = static_cast(UINT8_C(0)))
+ : base_class_type(initial_duty),
+ my_duty_shadow(initial_duty)
+ {
+ port_pin_type::set_pin_low();
+ port_pin_type::set_direction_output();
+ }
+
+ ~pwm_port() noexcept override = default;
+
+ auto init() noexcept -> bool override
+ {
+ return true;
+ }
+
+ static constexpr auto get_resolution() noexcept -> duty_type { return duty_type { UINT16_C(1000) }; }
+
+ auto set_duty(const duty_type duty_cycle) noexcept -> void override
+ {
+ my_duty_shadow = (std::min)(duty_cycle, get_resolution());
+ }
+
+ auto service() noexcept -> void
+ {
+ // Increment the cycle counter.
+ ++my_cycle_counter;
+
+ ((my_cycle_counter <= base_class_type::get_duty()) ? port_pin_type::set_pin_high() : port_pin_type::set_pin_low());
+
+ if(my_cycle_counter == get_resolution())
+ {
+ // Latch the duty cycle from the shadow register.
+ // This is done at the end of the running cycle.
+ base_class_type::set_duty(my_duty_shadow);
+
+ // Reset the cycle counter for a new PWM period.
+ my_cycle_counter = static_cast(UINT8_C(0));
+ }
+ }
+
+ private:
+ duty_type my_cycle_counter { };
+ duty_type my_duty_shadow { };
+ };
+
+ } // namespace pwm
+ } // namespace mcal
+
+#endif // MCAL_PWM_PORT_2023_08_23_H
diff --git a/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_dummy.h b/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_dummy.h
new file mode 100644
index 000000000..2deb3e08d
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_dummy.h
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 2022.
+// 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)
+//
+
+#ifndef MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H
+ #define MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H
+
+ #include
+
+ namespace mcal { namespace spi {
+
+ class spi_software_dummy : public util::communication_buffer_depth_one_byte // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+ {
+ private:
+ using base_class_type = util::communication_buffer_depth_one_byte;
+
+ public:
+ // This class implements a dummy SPI with no real functionality.
+
+ spi_software_dummy() = default;
+
+ ~spi_software_dummy() override = default;
+
+ auto send(const std::uint8_t byte_to_send) noexcept -> bool override
+ {
+ static_cast(byte_to_send);
+
+ base_class_type::recv_buffer = 0U;
+
+ return true;
+ }
+
+ auto select() -> void override { }
+ auto deselect() -> void override { }
+ };
+
+ } // namespace spi
+ } // namespace mcal
+
+#endif // MCAL_SPI_SOFTWARE_DUMMY_2020_04_10_H
diff --git a/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_port_driver.h b/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_port_driver.h
new file mode 100644
index 000000000..74bc0c60f
--- /dev/null
+++ b/examples/chapter09_08a/src/mcal_spi/mcal_spi_software_port_driver.h
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2020 - 2022.
+// 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)
+//
+
+#ifndef MCAL_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H
+ #define MCAL_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H
+
+ #include
+ #include
+ #include
+
+ #include
+
+ namespace mcal { namespace spi {
+
+ template
+ class spi_software_port_driver : public util::communication_buffer_depth_one_byte
+ {
+ private:
+ // Consider:
+ // https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
+
+ // Timing applies to both the master and the slave device.
+
+ // CPOL=0:
+ // The clock idles to 0 and each cycle consists
+ // of a pulse of 1. The leading edge is a rising edge
+ // and the trailing edge is a falling edge.
+
+ // CPHA=0:
+ // Data out changes on the trailing edge of the
+ // preceding clock cycle, while data in is captured
+ // on (or shortly after) the leading edge of the
+ // clock cycle.
+
+ using base_class_type = util::communication_buffer_depth_one_byte;
+
+ public:
+ spi_software_port_driver()
+ {
+ port_pin_csn__type::set_pin_high();
+ port_pin_sck__type::set_pin_low();
+ port_pin_mosi_type::set_pin_low();
+
+ port_pin_csn__type::set_direction_output();
+ port_pin_sck__type::set_direction_output();
+ port_pin_mosi_type::set_direction_output();
+ port_pin_miso_type::set_direction_input();
+ }
+
+ ~spi_software_port_driver() override = default;
+
+ auto send(const std::uint8_t byte_to_send) noexcept -> bool override
+ {
+ base_class_type::recv_buffer = 0U;
+
+ for(std::uint_fast8_t bit_mask = UINT8_C(0x80); bit_mask != UINT8_C(0); bit_mask = std::uint_fast8_t(bit_mask >> 1U))
+ {
+ ((std::uint_fast8_t(byte_to_send & bit_mask) != UINT8_C(0)) ? port_pin_mosi_type::set_pin_high()
+ : port_pin_mosi_type::set_pin_low());
+
+ mcal::helper::disable_all_interrupts();
+
+ port_pin_sck__type::set_pin_high();
+ mcal::helper::nop_maker();
+
+ port_pin_sck__type::set_pin_low ();
+ mcal::helper::nop_maker();
+
+ if(port_pin_miso_type::read_input_value())
+ {
+ base_class_type::recv_buffer =
+ base_class_type::buffer_type(base_class_type::recv_buffer | bit_mask);
+ }
+
+ mcal::helper::enable_all_interrupts();
+ }
+
+ return true;
+ }
+
+ auto select() -> void override { port_pin_csn__type::set_pin_low(); }
+ auto deselect() -> void override { port_pin_csn__type::set_pin_high(); }
+ };
+
+ template
+ class spi_software_port_driver : public util::communication_buffer_depth_one_byte
+ {
+ public:
+ spi_software_port_driver()
+ {
+ port_pin_csn__type::set_pin_high();
+ port_pin_sck__type::set_pin_low();
+ port_pin_mosi_type::set_pin_low();
+
+ port_pin_csn__type::set_direction_output();
+ port_pin_sck__type::set_direction_output();
+ port_pin_mosi_type::set_direction_output();
+ }
+
+ ~spi_software_port_driver() override = default;
+
+ auto send(const std::uint8_t byte_to_send) noexcept -> bool override
+ {
+ for(std::uint_fast8_t bit_mask = UINT8_C(0x80);
+ bit_mask != UINT8_C(0);
+ bit_mask = std::uint_fast8_t(bit_mask >> 1U))
+ {
+ ((std::uint_fast8_t(byte_to_send & bit_mask) != UINT8_C(0)) ? port_pin_mosi_type::set_pin_high()
+ : port_pin_mosi_type::set_pin_low());
+
+ mcal::helper::disable_all_interrupts();
+
+ port_pin_sck__type::set_pin_high();
+ port_pin_sck__type::set_pin_low();
+
+ mcal::helper::enable_all_interrupts();
+ }
+
+ return true;
+ }
+
+ auto select() -> void override { port_pin_csn__type::set_pin_low(); }
+ auto deselect() -> void override { port_pin_csn__type::set_pin_high(); }
+ };
+
+ } // namespace spi
+ } // namespace mcal
+
+#endif // MCAL_SPI_SOFTWARE_PORT_DRIVER_2020_04_09_H
diff --git a/examples/chapter09_08a/src/os/os.cpp b/examples/chapter09_08a/src/os/os.cpp
index 591e0ac8a..a1bd651a5 100644
--- a/examples/chapter09_08a/src/os/os.cpp
+++ b/examples/chapter09_08a/src/os/os.cpp
@@ -1,37 +1,44 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright Christopher Kormanyos 2007 - 2025.
+///////////////////////////////////////////////////////////////////////////////
+// Copyright Christopher Kormanyos 2007 - 2024.
// 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
-#include
#include
#include
#include
#include
-#include
-namespace
+namespace local
{
- using task_list_type = std::array;
+ using task_list_type = std::array