Lazuli
Loading...
Searching...
No Matches
clock_24.c
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-3.0-only
3 * This file is part of Lazuli.
4 */
5
14#include <stdint.h>
15
16#include <Lazuli/clock_24.h>
17#include <Lazuli/common.h>
18#include <Lazuli/config.h>
19
20#include <Lazuli/sys/clock_24.h>
21#include <Lazuli/sys/memory.h>
22
26static volatile Clock24 clock24 = {0};
27
32
45static bool
46IncrementUntil(volatile uint8_t * const value, const uint8_t comparator)
47{
48 if (*value >= comparator) {
49 *value = 0;
50
51 return true;
52 }
53
54 (*value)++;
55
56 return false;
57}
58
64static bool
66{
67 const uint8_t lastSecondInAMinute = 59;
68
69 return IncrementUntil(&clock24.seconds, lastSecondInAMinute);
70}
71
77static bool
79{
80 const uint8_t lastMinuteInAnHour = 59;
81
82 return IncrementUntil(&clock24.minutes, lastMinuteInAnHour);
83}
84
88static void
90{
91 const uint8_t lastHourInADay = 23;
92
93 IncrementUntil(&clock24.hours, lastHourInADay);
94}
95
96void
98{
100 static uint16_t ticksToNewSecond = 0;
101
102 if (++ticksToNewSecond < ticksInOneSecond) {
103 return;
104 }
105
106 ticksToNewSecond = 0;
107
108 /*
109 * The clock version integer will constantly increment from 0 to its maximum
110 * value.
111 * We can let it overflow as it is unsigned. Unsigned overflow is not an
112 * undefined behaviour in C89.
113 */
114 ++clockVersion;
115
116 if (IncrementSeconds()) {
117 if (IncrementMinutes()) {
119 }
120 }
121}
122
123/*
124 * The working of this function needs an explanation.
125 *
126 * While a user task reads all the fields of struct Clock24 clock24, the clock
127 * thick interrupt can occur and cause the kernel to update that same fields.
128 * If that happens we will obtain a copy of struct Clock24 clock24 that is
129 * corrupted. e.g. some of the fields with the previous value, and the others
130 * with the updated value.
131 *
132 * To avoid that, we use this kind of "optimistic access":
133 * A version number is associated to struct Clock24. As all of the fields of
134 * struct Clock24 and version number are updated by the kernel at the same time
135 * without being interrupted, the new values of the time fields in the struct
136 * will be associated to a new value of the version field.
137 * We first read the current version number, then read all the time fields, and
138 * finally read the version number again. If the two version numbers differ we
139 * then know that the kernel updated the struct Clock24 clock24 while we were
140 * accessing it.
141 *
142 * This works as long as the version number is declared with a type that is read
143 * and written atomically.
144 */
145void
146Lz_Clock24_Get(Clock24 * const userClock24)
147{
148 u_read_write_atomic_t version;
149
150 if (NULL == userClock24) {
151 return;
152 }
153
154 do {
155 version = clockVersion;
156 userClock24->hours = clock24.hours;
157 userClock24->minutes = clock24.minutes;
158 userClock24->seconds = clock24.seconds;
159 } while (version != clockVersion);
160}
unsigned int uint16_t
Represents a unsigned integer type with width of exactly 16 bits.
Definition stdint.h:94
unsigned char uint8_t
Represents a unsigned integer type with width of exactly 8 bits.
Definition stdint.h:89
static bool IncrementUntil(volatile uint8_t *const value, const uint8_t comparator)
Increment an uint8_t value, and reset it if it reaches the value in comparator.
Definition clock_24.c:46
void Lz_Clock24_Get(Clock24 *const userClock24)
Get the time on a 24-Hour clock.
Definition clock_24.c:146
void Clock24_Increment(void)
Increment the 24-Hour clock, taking into the account the resolution of the system clock.
Definition clock_24.c:97
static void IncrementHours(void)
Increment the hours of the system 24-Hour clock.
Definition clock_24.c:89
static bool IncrementMinutes(void)
Increment the minutes of the system 24-Hour clock.
Definition clock_24.c:78
static bool IncrementSeconds(void)
Increment the seconds of the system 24-Hour clock.
Definition clock_24.c:65
static volatile u_read_write_atomic_t clockVersion
The clock version value.
Definition clock_24.c:31
static volatile Clock24 clock24
The system Clock24.
Definition clock_24.c:26
24-Hour clock user interface.
Basic type definitions and useful macros.
#define NULL
NULL pointer.
Definition common.h:70
uint8_t u_read_write_atomic_t
Represents an unsigned integer that can be read and written atomically.
Definition common.h:109
Include appropriate config file.
const unsigned int LZ_CONFIG_SYSTEM_CLOCK_RESOLUTION_FREQUENCY
The operating system clock resolution frequency, in Hertz.
Memory management API.
Represents the type used to hold the time.
Definition clock_24.h:26
uint8_t seconds
Seconds.
Definition clock_24.h:29
uint8_t hours
Hours
Definition clock_24.h:27
uint8_t minutes
Minutes.
Definition clock_24.h:28
24-Hour clock kernel interface.