ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_sdramc.c
Go to the documentation of this file.
1
23
24#include "ra8_sdramc.h"
25
26#include <stdint.h>
27
28#include "ra8_attributes.h"
29#include "ra8_check.h"
30#include "ra8_err.h"
31#include "ra8_gpio_constants.h"
32#include "ra8_log.h"
33#include "ra8_pfs_regs.h"
34#include "ra8_port_constants.h"
35#include "ra8_port_utils.h"
37#include "ra8_sdramc_regs.h"
38#include "ra8_system_regs.h"
39
40static const char* s_tag = "SDRAM";
41
58typedef enum : uint32_t {
61 k_ra8_sdamod_be = 0x01UL,
63 k_ra8_sdir_init = 0x0088UL,
64 k_ra8_sdmod_lmr = 0x0230UL,
65 k_ra8_sdrfcr_init = 0xB383UL,
66 k_ra8_sdtr_init = 0x00053703UL,
69
78typedef enum : uint8_t {
84
94typedef enum : uint8_t {
97
102typedef enum : uint32_t {
105
120 /* A0..A12 */
134 /* BA0, BA1 */
137 /* DQ0..DQ31 */
170 /* CKE, SDCLK, DQM0, DQM1, DQM2, DQM3, WE, CAS, RAS, CS */
181};
182
206{
207 const uint32_t count = (uint32_t)(sizeof(s_sdram_bus_pins) / sizeof(s_sdram_bus_pins[0]));
208 for (uint32_t i = 0U; i < count; ++i) {
209 const ra8_err_t route_err =
211 if (route_err != k_ra8_ok) {
212 return route_err;
213 }
214 const ra8_err_t drive_err =
216 if (drive_err != k_ra8_ok) {
217 return drive_err;
218 }
219 }
220 return k_ra8_ok;
221}
222
246{
247 volatile const r_sdramc_regs_t* const reg = ra8_sdramc();
248 for (uint32_t spin = 0U; spin < (uint32_t)k_ra8_sdramc_spin_max; ++spin) {
249 if ((uint8_t)(reg->SDSR & mask) == 0U) {
250 return k_ra8_ok;
251 }
252 }
253 ra8_log_error(s_tag, "sdramc: SDSR status bits never cleared");
255}
256
258{
259 const ra8_err_t pin_err = internal_sdramc_route_pins();
260 if (pin_err != k_ra8_ok) {
261 ra8_log_error(s_tag, "sdramc: bus-pin routing failed");
262 return pin_err;
263 }
264
265 volatile r_sdramc_regs_t* const reg = ra8_sdramc();
266
267 /* HUM Ch 15.6.10: confirm SDSR is clear, then program the
268 * one-shot SDRAM Initialization Register. SDIR is writable only
269 * once after reset. */
271 if (err != k_ra8_ok) {
272 return err;
273 }
274 reg->SDIR = (uint16_t)k_ra8_sdir_init;
275 reg->SDCCR = (uint8_t)k_ra8_sdccr_cfg_32bit;
276
277 /* Enable the SDCLK output to the device (PRCR-gated, CGC group). */
279 {
281 }
282
283 /* Run the hardware init sequencer (precharge-all + auto-refresh). */
284 reg->SDICR = (uint8_t)k_ra8_sdramc_kick;
286 if (err != k_ra8_ok) {
287 return err;
288 }
289
290 /* Access + endian mode, then issue the LMR command (SDMOD).
291 * SDAMOD.BE = 1 keeps multi-beat accesses continuous so the
292 * sub-word address increments correctly. */
293 reg->SDAMOD = (uint8_t)k_ra8_sdamod_be;
294 reg->SDCMOD = 0U;
295 err = internal_sdramc_wait((uint8_t)k_ra8_sdsr_all);
296 if (err != k_ra8_ok) {
297 return err;
298 }
299 reg->SDMOD = (uint16_t)k_ra8_sdmod_lmr;
301 if (err != k_ra8_ok) {
302 return err;
303 }
304
305 /* Timing, address-multiplex, refresh -- then enable SDRAM access. */
306 reg->SDTR = (uint32_t)k_ra8_sdtr_init;
307 reg->SDADR = (uint8_t)k_ra8_sdadr_mxc_9col;
308 reg->SDRFCR = (uint16_t)k_ra8_sdrfcr_init;
309 reg->SDRFEN = (uint8_t)k_ra8_sdramc_kick;
310 reg->SDCCR = (uint8_t)k_ra8_sdccr_enable;
311
312 ra8_log_info(s_tag, "sdramc_init (64 MiB @ 0x68000000)");
313 return k_ra8_ok;
314}
315
316/* =============================================================================
317 * lifecycle + power
318 * =============================================================================
319 */
320
322{
323 volatile r_sdramc_regs_t* reg = ra8_sdramc();
324 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
325 reg->SDRFEN = 0U;
326 /* HUM Ch 15.3.11 "SDCCR : SDC Control Register" p 605 */
327 reg->SDCCR = 0U;
328 return k_ra8_ok;
329}
330
332{
333 /* HUM Ch 15.3.15 "SDRFCR : SDRAM Refresh Control Register" p 607 */
334 ra8_sdramc()->SDRFCR = sdrfcr;
335 return k_ra8_ok;
336}
337
338ra8_err_t ra8_sdramc_get_status(uint8_t* out_enabled)
339{
340 RA8_CHECK_NULL_PTR(out_enabled, s_tag, "out_enabled must not be nullptr");
341 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
342 *out_enabled = ra8_sdramc()->SDRFEN;
343 return k_ra8_ok;
344}
345
347{
348 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
349 ra8_sdramc()->SDRFEN = 0U;
350 return k_ra8_ok;
351}
352
354{
355 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
356 ra8_sdramc()->SDRFEN = (uint8_t)k_ra8_sdramc_kick;
357 return k_ra8_ok;
358}
359
361{
362 volatile r_sdramc_regs_t* const reg = ra8_sdramc();
363
364 /* Precondition 1: all SDSR status bits must be clear before writing
365 * SDSELF.SFEN (HUM Table 15.8 requirement). */
366 /* HUM Ch 15.3.22 "SDSR : SDRAM Status Register" p 613 */
367 if ((uint8_t)(reg->SDSR & (uint8_t)k_ra8_sdsr_all) != 0U) {
368 ra8_log_error(s_tag, "sdramc: SDSR busy on self-refresh entry");
370 }
371
372 /* Precondition 2: SDSELF.SFEN must be 0 -- already in self-refresh
373 * is a caller error. */
374 /* HUM Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606 */
375 if ((uint8_t)(reg->SDSELF & (uint8_t)k_ra8_sdself_sfen) != 0U) {
376 ra8_log_error(s_tag, "sdramc: already in self-refresh");
378 }
379
380 /* Disable auto-refresh before asserting self-refresh. */
381 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
382 reg->SDRFEN = 0U;
383
384 /* Assert SFEN: the hardware issues a final auto-refresh then
385 * switches the SDRAM to self-refresh mode. */
386 /* HUM Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606 */
387 reg->SDSELF = (uint8_t)k_ra8_sdself_sfen;
388
389 /* Wait for the transition to complete (SRFST clears when the
390 * SDRAM has entered self-refresh). */
391 const ra8_err_t err = internal_sdramc_wait((uint8_t)k_ra8_sdsr_srfst);
392 if (err != k_ra8_ok) {
393 return err;
394 }
395
396 ra8_log_info(s_tag, "sdramc: entered self-refresh");
397 return k_ra8_ok;
398}
399
401{
402 volatile r_sdramc_regs_t* const reg = ra8_sdramc();
403
404 /* Precondition 1: SDSELF.SFEN must be 1 -- must be in self-refresh
405 * before exiting. */
406 /* HUM Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606 */
407 if ((uint8_t)(reg->SDSELF & (uint8_t)k_ra8_sdself_sfen) == 0U) {
408 ra8_log_error(s_tag, "sdramc: not in self-refresh on exit");
410 }
411
412 /* Precondition 2: SDSR.SRFST must be clear -- no transition may be
413 * in progress when writing SDSELF. */
414 /* HUM Ch 15.3.22 "SDSR : SDRAM Status Register" p 613 */
415 if ((uint8_t)(reg->SDSR & (uint8_t)k_ra8_sdsr_srfst) != 0U) {
416 ra8_log_error(s_tag, "sdramc: SDSR SRFST busy on self-refresh exit");
418 }
419
420 /* Clear SFEN: the hardware performs the self-refresh clearing
421 * cycles (count set by SDRFCR.REFW) then returns to normal. */
422 /* HUM Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606 */
423 reg->SDSELF = 0U;
424
425 /* Wait for the recovery to complete (SRFST clears when auto-
426 * refresh is ready to resume). */
427 const ra8_err_t err = internal_sdramc_wait((uint8_t)k_ra8_sdsr_srfst);
428 if (err != k_ra8_ok) {
429 return err;
430 }
431
432 /* Re-enable the auto-refresh engine. */
433 /* HUM Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608 */
434 reg->SDRFEN = (uint8_t)k_ra8_sdramc_kick;
435
436 ra8_log_info(s_tag, "sdramc: exited self-refresh");
437 return k_ra8_ok;
438}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#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_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ 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
PSEL codes for peripheral pin routing on the RA8D2.
@ k_ra8_psel_bus
01011b: External BUS interface.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
Pin Function Select (PFS) register layout for the Renesas RA8D2.
@ k_ra8_pfs_dscr_high_speed_high
10b: High-speed high drive.
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_port_13
RA8 port 13.
@ k_ra8_port_12
RA8 port 12.
@ k_ra8_port_3
RA8 port 3.
@ k_ra8_port_6
RA8 port 6.
@ k_ra8_port_5
RA8 port 5.
@ k_ra8_port_8
RA8 port 8.
@ k_ra8_port_1
RA8 port 1.
@ k_ra8_port_10
RA8 port 10.
#define RA8_PIN(port, pin)
Build a ra8_port_pin_t from explicit port / pin indices.
@ k_ra8_pin_4
RA8 pin 4.
@ k_ra8_pin_6
RA8 pin 6.
@ k_ra8_pin_11
RA8 pin 11.
@ k_ra8_pin_7
RA8 pin 7.
@ k_ra8_pin_10
RA8 pin 10.
@ k_ra8_pin_1
RA8 pin 1.
@ k_ra8_pin_2
RA8 pin 2.
@ k_ra8_pin_13
RA8 pin 13.
@ k_ra8_pin_12
RA8 pin 12.
@ k_ra8_pin_5
RA8 pin 5.
@ k_ra8_pin_14
RA8 pin 14.
@ k_ra8_pin_9
RA8 pin 9.
@ k_ra8_pin_8
RA8 pin 8.
@ k_ra8_pin_0
RA8 pin 0.
@ k_ra8_pin_3
RA8 pin 3.
@ k_ra8_pin_15
RA8 pin 15.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_pfs_set_drive_strength(ra8_port_pin_t pin, ra8_pfs_dscr_t dscr)
Set the output drive strength (PmnPFS.DSCR) of an already-routed pin.
Definition gpio.c:287
ra8_err_t ra8_pfs_route_peripheral(ra8_port_pin_t pin, ra8_psel_t psel, const char *owner)
Route a pin to a non-IRQ peripheral function via PFS.PSEL.
Definition gpio.c:238
Scoped PRCR unlock helper.
#define RA8_PROTECTED_WRITE(unlock_val)
Scoped PRCR unlock block.
static ra8_err_t internal_sdramc_wait(uint8_t mask)
Spin until the masked SDSR status bits clear.
Definition ra8_sdramc.c:245
static ra8_err_t internal_sdramc_route_pins(void)
Route every SDRAM parallel-bus pin to the external-bus mux.
Definition ra8_sdramc.c:205
ra8_sdramc_reg_val_t
SDRAMC register values for the EK-RA8D2 IS42S32160F SDRAM.
Definition ra8_sdramc.c:58
@ k_ra8_sdrfcr_init
SDRFCR: REFW=12cyc, refresh/900cyc(7.2us).
Definition ra8_sdramc.c:65
@ k_ra8_sdccr_enable
SDCCR: BSIZE=01, EXENB=1.
Definition ra8_sdramc.c:60
@ k_ra8_sdmod_lmr
SDMOD: WB=single, CL=3, BT=seq, BL=1.
Definition ra8_sdramc.c:64
@ k_ra8_sdramc_kick
Generic "set bit 0" kick value.
Definition ra8_sdramc.c:67
@ k_ra8_sdtr_init
SDTR: RAS=6,RCD=4,RP=4,WR=2,CL=3 cyc.
Definition ra8_sdramc.c:66
@ k_ra8_sdir_init
SDIR: ARFI=11cyc, ARFC=8x, PRC=3cyc.
Definition ra8_sdramc.c:63
@ k_ra8_sdamod_be
SDAMOD.BE=1: continuous access on.
Definition ra8_sdramc.c:61
@ k_ra8_sdccr_cfg_32bit
SDCCR: BSIZE=01 (32-bit), EXENB=0.
Definition ra8_sdramc.c:59
@ k_ra8_sdadr_mxc_9col
SDADR.MXC=01b: 9-bit column shift.
Definition ra8_sdramc.c:62
ra8_sdramc_spin_t
Upper bound for the SDSR status-poll loops (NASA P10 Rule 2).
Definition ra8_sdramc.c:102
@ k_ra8_sdramc_spin_max
~ms at 1 GHz; init takes < 1 us.
Definition ra8_sdramc.c:103
ra8_sdramc_sdsr_t
SDRAM Status Register (SDSR) bit masks.
Definition ra8_sdramc.c:78
@ k_ra8_sdsr_all
MRSST | INIST | SRFST: all blocking bits.
Definition ra8_sdramc.c:82
@ k_ra8_sdsr_srfst
SRFST (bit 4): self-refresh transition/recovery in progress.
Definition ra8_sdramc.c:81
@ k_ra8_sdsr_mrsst
MRSST (bit 0): mode-register-set in progress.
Definition ra8_sdramc.c:79
@ k_ra8_sdsr_inist
INIST (bit 3): init sequence in progress.
Definition ra8_sdramc.c:80
ra8_err_t ra8_sdramc_enter_stop(void)
Disable auto-refresh for deep-sleep entry.
Definition ra8_sdramc.c:346
ra8_err_t ra8_sdramc_exit_stop(void)
Re-enable auto-refresh after wake-up.
Definition ra8_sdramc.c:353
ra8_sdramc_sdself_t
SDRAM Self-Refresh Control Register (SDSELF) bit values.
Definition ra8_sdramc.c:94
@ k_ra8_sdself_sfen
SFEN (bit 0): self-refresh enable.
Definition ra8_sdramc.c:95
ra8_err_t ra8_sdramc_init(void)
Initialise the external SDRAM at k_ra8_sdram_base_addr.
Definition ra8_sdramc.c:257
static const ra8_port_pin_t s_sdram_bus_pins[]
The 57 EK-RA8D2 parallel-bus pins the SDRAMC drives.
Definition ra8_sdramc.c:119
ra8_err_t ra8_sdramc_exit_self_refresh(void)
Exit SDRAM self-refresh and resume normal auto-refresh operation.
Definition ra8_sdramc.c:400
ra8_err_t ra8_sdramc_enter_self_refresh(void)
Put the external SDRAM into JEDEC self-refresh mode.
Definition ra8_sdramc.c:360
ra8_err_t ra8_sdramc_get_status(uint8_t *out_enabled)
Read the refresh-enable bit as a status mask.
Definition ra8_sdramc.c:338
ra8_err_t ra8_sdramc_set_refresh_interval(uint16_t sdrfcr)
Change the SDRAM auto-refresh interval at runtime.
Definition ra8_sdramc.c:331
ra8_err_t ra8_sdramc_deinit(void)
Tear down the SDRAM controller (disable refresh, clear SDICR).
Definition ra8_sdramc.c:321
External SDRAM controller driver (framework).
External SDRAM controller register layout for the Renesas RA8D2.
static volatile uint8_t * ra8_sdramc_sdckocr(void)
Get pointer to the R_SYSTEM SDCLK-output control register.
static volatile r_sdramc_regs_t * ra8_sdramc(void)
Get pointer to the SDRAMC register block.
System Control (SYSC) register layout for the Renesas RA8D2.
@ k_ra8_prcr_unlock_cgc
RA8 prcr unlock cgc.
SDRAM controller register window.
volatile uint8_t SDCMOD
SDC Mode Register.
volatile uint8_t SDICR
Init Sequence Control.
volatile uint8_t SDSR
SDRAM Status Register (RO).
volatile uint16_t SDIR
SDRAM Initialization Register.
volatile uint8_t SDSELF
SDRAM Self-Refresh Control.
volatile uint16_t SDMOD
SDRAM Mode Register.
volatile uint32_t SDTR
SDRAM Timing Register.
volatile uint16_t SDRFCR
SDRAM Refresh Control.
volatile uint8_t SDRFEN
SDRAM Auto-Refresh Control.
volatile uint8_t SDAMOD
SDRAM Access Mode Register.
volatile uint8_t SDCCR
SDC Control Register.
volatile uint8_t SDADR
SDRAM Address Register.