ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_acmphs.c
Go to the documentation of this file.
1
19
20#include "ra8_acmphs.h"
21
22#include <stdint.h>
23
24#include "ra8_acmphs_regs.h"
25#include "ra8_attributes.h"
26#include "ra8_check.h"
27#include "ra8_err.h"
28#include "ra8_log.h"
29#include "ra8_mstp.h"
30#include "ra8_port_constants.h"
31
32static const char* s_tag = "ACMPHS";
33
46typedef enum : uint8_t {
49
60
82{
83 volatile r_acmphs_regs_t* reg = ra8_acmphs(ch);
84 if (reg == nullptr) { /* GCOVR_EXCL_BR_LINE -- ch already bounded */
85 return k_ra8_err_hw_init_failed; /* GCOVR_EXCL_LINE -- MSTP/reset HW-only */
86 }
88 /* HUM Ch 11.2.9 "MSTPCRD : Module Stop Control Register D", p 449 */
90 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
91 RA8_RETURN_ON_ERROR(mst_err, s_tag, "acmphs_init: mstp enable");
92 /* GCOVR_EXCL_BR_STOP */
93 }
94 reg->CMPCTL = 0U;
95 reg->CMPSEL0 = 0U;
96 reg->CMPSEL1 = 0U;
97 reg->CPIOC = 0U;
98 return k_ra8_ok;
99}
100
101[[nodiscard]] ra8_err_t ra8_acmphs_init(void)
102{
103 for (uint8_t ch = 0U; ch < (uint8_t)k_ra8_acmphs_channel_count; ++ch) {
104 const ra8_err_t err = internal_reset_channel(ch);
105 /* GCOVR_EXCL_BR_START -- HW reset readback */
106 RA8_RETURN_ON_ERROR(err, s_tag, "acmphs_init channel reset");
107 /* GCOVR_EXCL_BR_STOP */
108 }
109 ra8_log_info(s_tag, "acmphs_init");
110 return k_ra8_ok;
111}
112
113[[nodiscard]] ra8_err_t ra8_acmphs_channel_enable(uint8_t channel)
114{
115 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
117 }
118 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
119 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
120
121 const uint8_t current = reg->CMPCTL;
122 reg->CMPCTL = (uint8_t)(current | k_ra8_acmphs_mask_hcen);
123 ra8_log_info_val(s_tag, "enable channel", (uint32_t)channel);
124 return k_ra8_ok;
125}
126
127[[nodiscard]] ra8_err_t ra8_acmphs_read_output(uint8_t channel, ra8_level_t* out)
128{
129 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
130 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
132 }
133 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
134 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
135
136 const uint8_t monitor = reg->CMPMON;
137 if ((monitor & k_ra8_acmphs_mask_hcmon) != 0U) {
138 *out = k_ra8_level_high;
139 } else {
140 *out = k_ra8_level_low;
141 }
142 return k_ra8_ok;
143}
144
145/* =============================================================================
146 * full build-out
147 * =============================================================================
148 */
149
162
164static void* s_acmphs_ctx;
165
167{
168 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
169 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
171 }
172 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
173 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
174
175 if (channel < k_ra8_acmphs_mstp_id_count) {
176 const ra8_err_t mst_err = ra8_mstp_enable(s_acmphs_mstp_table[channel]);
177 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
178 RA8_RETURN_ON_ERROR(mst_err, s_tag, "acmphs_init: mstp");
179 /* GCOVR_EXCL_BR_STOP */
180 }
181
182 reg->CMPSEL0 = cfg->ivpsel;
183 reg->CMPSEL1 = cfg->ivrefsel;
184
185 /* FSP CMPCTL packs the filter select into CDFS[1:0] @ [6:5]. There
186 * is no standalone CMPFIR register on RA8D2; the driver maps its
187 * boolean filter_en into CDFS = 0 (off) or 1 (base sampling). */
188 uint8_t ctl = k_ra8_acmphs_mask_hcen;
189 ctl |= (uint8_t)((uint8_t)cfg->edge << k_ra8_acmphs_ceg_shift);
190 if (cfg->invert_out) {
192 }
193 if (cfg->filter_en) {
195 }
196 reg->CMPCTL = ctl;
197 return k_ra8_ok;
198}
199
201{
202 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
204 }
205 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
206 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
207
208 reg->CMPCTL = 0U;
209 reg->CMPSEL0 = 0U;
210 reg->CMPSEL1 = 0U;
211 if (channel < k_ra8_acmphs_mstp_id_count) {
213 }
214 return k_ra8_ok;
215}
216
217ra8_err_t ra8_acmphs_set_inputs(uint8_t channel, uint8_t ivpsel, uint8_t ivrefsel)
218{
219 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
221 }
222 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
223 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
224
225 reg->CMPSEL0 = ivpsel;
226 reg->CMPSEL1 = ivrefsel;
227 return k_ra8_ok;
228}
229
230ra8_err_t ra8_acmphs_get_status(uint8_t channel, uint8_t* out_mask)
231{
232 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
233 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
235 }
236 volatile const r_acmphs_regs_t* reg = ra8_acmphs(channel);
237 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
238
239 *out_mask = (uint8_t)(reg->CMPCTL & k_ra8_acmphs_ctl_mask);
240 return k_ra8_ok;
241}
242
244{
245 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
247 }
248 volatile r_acmphs_regs_t* reg = ra8_acmphs(channel);
249 RA8_CHECK_NULL_PTR(reg, s_tag, "channel mapping failed");
250
251 reg->CMPCTL = 0U;
252 return k_ra8_ok;
253}
254
256{
257 s_acmphs_fn = fn;
258 s_acmphs_ctx = ctx;
259 return k_ra8_ok;
260}
261
263{
264 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
266 }
267 if (channel < k_ra8_acmphs_mstp_id_count) {
268 return ra8_mstp_disable(s_acmphs_mstp_table[channel]);
269 }
270 return k_ra8_ok;
271}
272
274{
275 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
277 }
278 if (channel < k_ra8_acmphs_mstp_id_count) {
279 return ra8_mstp_enable(s_acmphs_mstp_table[channel]);
280 }
281 return k_ra8_ok;
282}
283
285void ra8_acmphs_dispatch(uint8_t channel)
286{
287 if ((uint16_t)channel >= k_ra8_acmphs_channel_count) {
288 return;
289 }
291 void* const ctx = s_acmphs_ctx;
292 if (fn != nullptr) {
293 fn(ctx, channel);
294 }
295}
ra8_err_t ra8_acmphs_channel_enable(uint8_t channel)
Enable a single ACMPHS channel.
Definition ra8_acmphs.c:113
ra8_err_t ra8_acmphs_set_inputs(uint8_t channel, uint8_t ivpsel, uint8_t ivrefsel)
Change the input selection of one channel at runtime.
Definition ra8_acmphs.c:217
void ra8_acmphs_dispatch(uint8_t channel)
Dispatch an ACMPHS edge event – fire the registered callback.
Definition ra8_acmphs.c:285
static void * s_acmphs_ctx
Definition ra8_acmphs.c:164
ra8_err_t ra8_acmphs_channel_init(uint8_t channel, const ra8_acmphs_cfg_t *cfg)
Initialise one channel with a full config descriptor.
Definition ra8_acmphs.c:166
ra8_err_t ra8_acmphs_channel_deinit(uint8_t channel)
Tear down one channel (disable + clear CMPCTL).
Definition ra8_acmphs.c:200
ra8_err_t ra8_acmphs_read_output(uint8_t channel, ra8_level_t *out)
Read the live output of a channel.
Definition ra8_acmphs.c:127
ra8_err_t ra8_acmphs_exit_stop(uint8_t channel)
Exit MSTP-gated stop for one channel.
Definition ra8_acmphs.c:273
ra8_err_t ra8_acmphs_enter_stop(uint8_t channel)
Put one channel into MSTP-gated stop.
Definition ra8_acmphs.c:262
ra8_err_t ra8_acmphs_get_status(uint8_t channel, uint8_t *out_mask)
Read CMPCTL enable / edge bits.
Definition ra8_acmphs.c:230
ra8_acmphs_mstp_limit_t
Number of ACMPHS channels that have dedicated MSTPD bits.
Definition ra8_acmphs.c:46
@ k_ra8_acmphs_mstp_id_count
RA8 acmphs mstp ID count.
Definition ra8_acmphs.c:47
static ra8_err_t internal_reset_channel(uint8_t ch)
Reset one ACMPHS channel's control + selector registers.
Definition ra8_acmphs.c:81
static ra8_acmphs_event_fn_t s_acmphs_fn
Definition ra8_acmphs.c:163
ra8_err_t ra8_acmphs_clear_status(uint8_t channel)
Clear CMPCTL (disable + edge mode off) for one channel.
Definition ra8_acmphs.c:243
ra8_acmphs_bits_t
CMPCTL field shifts (match FSP R_ACMPHS0_CMPCTL_b).
Definition ra8_acmphs.c:154
@ k_ra8_acmphs_ceg_shift
CMPCTL.CEG[1:0] at [4:3].
Definition ra8_acmphs.c:155
@ k_ra8_acmphs_cdfs_shift
CMPCTL.CDFS[1:0] at [6:5].
Definition ra8_acmphs.c:156
@ k_ra8_acmphs_cdfs_enabled_value
"Any sampling clock" when filter on.
Definition ra8_acmphs.c:157
@ k_ra8_acmphs_ctl_mask
RA8 acmphs ctl mask.
Definition ra8_acmphs.c:158
ra8_err_t ra8_acmphs_init(void)
Legacy init – reset every channel to its power-on state.
Definition ra8_acmphs.c:101
ra8_err_t ra8_acmphs_attach_handler(ra8_acmphs_event_fn_t fn, void *ctx)
Attach an ACMPHS event callback (shared across all channels).
Definition ra8_acmphs.c:255
static const ra8_mstp_t s_acmphs_mstp_table[k_ra8_acmphs_mstp_id_count]
Channel-index -> MSTP id lookup for the first 4 channels.
Definition ra8_acmphs.c:54
Full-featured High-Speed Analog Comparator (ACMPHS) driver.
void(* ra8_acmphs_event_fn_t)(void *ctx, uint8_t channel)
ACMPHS edge event callback.
Definition ra8_acmphs.h:65
High-Speed Analog Comparator (ACMPHS) register layout for the RA8D2.
static volatile r_acmphs_regs_t * ra8_acmphs(uint8_t channel)
Get pointer to ACMPHS channel channel.
@ k_ra8_acmphs_mask_cinv
CINV bit.
@ k_ra8_acmphs_mask_coe
COE bit.
@ k_ra8_acmphs_mask_hcmon
CMPMON.CMPMON: output level read.
@ k_ra8_acmphs_mask_hcen
HCMPON operation enable.
@ k_ra8_acmphs_mask_ceg
CEG[1:0] @ [4:3] edge selector.
@ k_ra8_acmphs_mask_cdfs
CDFS[1:0] @ [6:5] noise filter.
@ k_ra8_acmphs_channel_count
Channels 0..5 on this package.
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
ra8_mstp_t
Packed (reg << 8) | bit module-stop identifier.
@ k_ra8_mstp_acmphs0
MSTPD28 ACMPHS0.
@ k_ra8_mstp_acmphs3
MSTPD25 ACMPHS3.
@ k_ra8_mstp_acmphs2
MSTPD26 ACMPHS2.
@ k_ra8_mstp_acmphs1
MSTPD27 ACMPHS1.
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_level_t
Digital output / input level.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
Per-channel ACMPHS register window.
volatile uint8_t CMPCTL
+0x00 Control (enable, edges, filter).
volatile uint8_t CMPSEL0
+0x04 Plus-input selection.
volatile uint8_t CPIOC
+0x10 Output polarity / pin control.
volatile uint8_t CMPSEL1
+0x08 Minus-input selection.
volatile uint8_t CMPMON
+0x0C Output monitor (read-only).
Configuration descriptor for ra8_acmphs_channel_init.
Definition ra8_acmphs.h:51
uint8_t ivpsel
Plus-input select (CMPSEL0).
Definition ra8_acmphs.h:52
bool invert_out
True -> invert output.
Definition ra8_acmphs.h:56
ra8_acmphs_edge_t edge
Edge detect mode.
Definition ra8_acmphs.h:54
bool filter_en
True -> enable filter.
Definition ra8_acmphs.h:55
uint8_t ivrefsel
Minus-input select (CMPSEL1).
Definition ra8_acmphs.h:53