ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_sdramc.c File Reference

SDRAM controller driver implementation. More...

#include "ra8_sdramc.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_gpio_constants.h"
#include "ra8_log.h"
#include "ra8_pfs_regs.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_register_protection.h"
#include "ra8_sdramc_regs.h"
#include "ra8_system_regs.h"
Include dependency graph for ra8_sdramc.c:

Go to the source code of this file.

Enumerations

enum  ra8_sdramc_reg_val_t : uint32_t {
  k_ra8_sdccr_cfg_32bit = 0x10UL ,
  k_ra8_sdccr_enable = 0x11UL ,
  k_ra8_sdamod_be = 0x01UL ,
  k_ra8_sdadr_mxc_9col = 0x01UL ,
  k_ra8_sdir_init = 0x0088UL ,
  k_ra8_sdmod_lmr = 0x0230UL ,
  k_ra8_sdrfcr_init = 0xB383UL ,
  k_ra8_sdtr_init = 0x00053703UL ,
  k_ra8_sdramc_kick = 0x01UL
}
 SDRAMC register values for the EK-RA8D2 IS42S32160F SDRAM. More...
enum  ra8_sdramc_sdsr_t : uint8_t {
  k_ra8_sdsr_mrsst = 0x01U ,
  k_ra8_sdsr_inist = 0x08U ,
  k_ra8_sdsr_srfst = 0x10U ,
  k_ra8_sdsr_all = 0x19U
}
 SDRAM Status Register (SDSR) bit masks. More...
enum  ra8_sdramc_sdself_t : uint8_t { k_ra8_sdself_sfen = 0x01U }
 SDRAM Self-Refresh Control Register (SDSELF) bit values. More...
enum  ra8_sdramc_spin_t : uint32_t { k_ra8_sdramc_spin_max = 1000000U }
 Upper bound for the SDSR status-poll loops (NASA P10 Rule 2). More...

Functions

static ra8_err_t internal_sdramc_route_pins (void)
 Route every SDRAM parallel-bus pin to the external-bus mux.
static ra8_err_t internal_sdramc_wait (uint8_t mask)
 Spin until the masked SDSR status bits clear.
ra8_err_t ra8_sdramc_init (void)
 Initialise the external SDRAM at k_ra8_sdram_base_addr.
ra8_err_t ra8_sdramc_deinit (void)
 Tear down the SDRAM controller (disable refresh, clear SDICR).
ra8_err_t ra8_sdramc_set_refresh_interval (uint16_t sdrfcr)
 Change the SDRAM auto-refresh interval at runtime.
ra8_err_t ra8_sdramc_get_status (uint8_t *out_enabled)
 Read the refresh-enable bit as a status mask.
ra8_err_t ra8_sdramc_enter_stop (void)
 Disable auto-refresh for deep-sleep entry.
ra8_err_t ra8_sdramc_exit_stop (void)
 Re-enable auto-refresh after wake-up.
ra8_err_t ra8_sdramc_enter_self_refresh (void)
 Put the external SDRAM into JEDEC self-refresh mode.
ra8_err_t ra8_sdramc_exit_self_refresh (void)
 Exit SDRAM self-refresh and resume normal auto-refresh operation.

Variables

static const char * s_tag = "SDRAM"
static const ra8_port_pin_t s_sdram_bus_pins []
 The 57 EK-RA8D2 parallel-bus pins the SDRAMC drives.

Detailed Description

SDRAM controller driver implementation.

Tag
[Ring 3 / HAL] {World: S}

Driver for the RA8D2 SDRAM controller block (the SDRAMC sub-block of R_BUS, HUM Ch 15 "Buses"). Brings up the on-board SDRAM of the EK-RA8D2 – an ISSI IS42S32160F, 512 Mbit (64 MB) organised as 16M x 32 bits, 13 row / 9 column / 4 bank – mapped at k_ra8_sdram_base_addr (0x68000000).

Bring-up follows the HUM SDRAMC initialization sequence and FSP R_BSP_SdramInit: route the parallel-bus pins, enable the SDCLK output, run the hardware init sequencer, issue the LMR command, program the timing/refresh registers, then enable SDRAM access.

Definition in file ra8_sdramc.c.

Enumeration Type Documentation

◆ ra8_sdramc_reg_val_t

enum ra8_sdramc_reg_val_t : uint32_t

SDRAMC register values for the EK-RA8D2 IS42S32160F SDRAM.

The device is a 512 Mbit x32 SDR SDRAM (13 row / 9 column / 4 bank). SDCLK runs at BCLK = 125 MHz (8 ns). Timing fields hold a conservative cycle count: RCD/RP carry a spare cycle over the datasheet minimum, and the auto-refresh request interval (900 cycles = 7.2 us) sits comfortably under the 7.8 us-per-row JEDEC limit so a slow-side SDCLK tolerance cannot starve a row. The HUM (Ch 15.3.20 SDTR / 15.3.15 SDRFCR) encodes RP/RAI as (cycles - 1) and RCD/CL/REFW likewise as one-less-than-cycles.

Invariant
All values target a 32-bit data bus, CAS latency 3.
Enumerator
k_ra8_sdccr_cfg_32bit 

SDCCR: BSIZE=01 (32-bit), EXENB=0.

k_ra8_sdccr_enable 

SDCCR: BSIZE=01, EXENB=1.

k_ra8_sdamod_be 

SDAMOD.BE=1: continuous access on.

k_ra8_sdadr_mxc_9col 

SDADR.MXC=01b: 9-bit column shift.

k_ra8_sdir_init 

SDIR: ARFI=11cyc, ARFC=8x, PRC=3cyc.

k_ra8_sdmod_lmr 

SDMOD: WB=single, CL=3, BT=seq, BL=1.

k_ra8_sdrfcr_init 

SDRFCR: REFW=12cyc, refresh/900cyc(7.2us).

k_ra8_sdtr_init 

SDTR: RAS=6,RCD=4,RP=4,WR=2,CL=3 cyc.

k_ra8_sdramc_kick 

Generic "set bit 0" kick value.

Definition at line 58 of file ra8_sdramc.c.

◆ ra8_sdramc_sdself_t

enum ra8_sdramc_sdself_t : uint8_t

SDRAM Self-Refresh Control Register (SDSELF) bit values.

HUM Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606: the SFEN bit controls the self-refresh state. Setting SFEN=1 initiates an auto-refresh cycle then self-refresh; clearing it ends self-refresh and auto-refresh resumes.

Enumerator
k_ra8_sdself_sfen 

SFEN (bit 0): self-refresh enable.

Definition at line 94 of file ra8_sdramc.c.

◆ ra8_sdramc_sdsr_t

enum ra8_sdramc_sdsr_t : uint8_t

SDRAM Status Register (SDSR) bit masks.

HUM Ch 15.3.22 "SDSR : SDRAM Status Register" p 613: the SDRAMC init/LMR/self-refresh steps must wait for the relevant status bit to clear before issuing the next register write.

Enumerator
k_ra8_sdsr_mrsst 

MRSST (bit 0): mode-register-set in progress.

k_ra8_sdsr_inist 

INIST (bit 3): init sequence in progress.

k_ra8_sdsr_srfst 

SRFST (bit 4): self-refresh transition/recovery in progress.

k_ra8_sdsr_all 

MRSST | INIST | SRFST: all blocking bits.

Definition at line 78 of file ra8_sdramc.c.

◆ ra8_sdramc_spin_t

enum ra8_sdramc_spin_t : uint32_t

Upper bound for the SDSR status-poll loops (NASA P10 Rule 2).

Enumerator
k_ra8_sdramc_spin_max 

~ms at 1 GHz; init takes < 1 us.

Definition at line 102 of file ra8_sdramc.c.

Function Documentation

◆ internal_sdramc_route_pins()

ra8_err_t internal_sdramc_route_pins ( void )
static

Route every SDRAM parallel-bus pin to the external-bus mux.

Walks s_sdram_bus_pins, muxing each to PSEL = k_ra8_psel_bus and raising its drive strength to high-speed/high – the 125 MHz SDCLK pin requires it per the RA8D2 datasheet, and the address/data/ control pins need it to meet the SDRAM setup/hold window.

Returns
ra8_err_t Error code.
Return values
k_ra8_okAll bus pins routed.
k_ra8_err_gpio_conflictA pin is already owned elsewhere.
k_ra8_err_gpio_invalid_pinA pin index was rejected.
Precondition
IOPORT power is on (MSTPCRB cleared for IOPORT).
Caller runs single-threaded during board init.
Postcondition
On k_ra8_ok every bus pin carries its SDRAMC signal.
On error the routing is left partially applied.
Note
Not thread-safe.
Since
0.1.0

Definition at line 205 of file ra8_sdramc.c.

References k_ra8_ok, k_ra8_pfs_dscr_high_speed_high, k_ra8_psel_bus, RA8_INTERNAL, ra8_pfs_route_peripheral(), ra8_pfs_set_drive_strength(), and s_sdram_bus_pins.

Referenced by ra8_sdramc_init().

◆ internal_sdramc_wait()

ra8_err_t internal_sdramc_wait ( uint8_t mask)
static

Spin until the masked SDSR status bits clear.

The HUM requires confirming that the relevant SDSR bits are 0 before SDICR / SDMOD / further control writes. The loop is bounded by k_ra8_sdramc_spin_max so a wedged controller cannot hang init.

Parameters
[in]maskSDSR bit mask to wait on (ra8_sdramc_sdsr_t).
Returns
ra8_err_t Error code.
Return values
k_ra8_okMasked bits read 0.
k_ra8_err_hw_timeoutBits never cleared within the bound.
Precondition
mask is a subset of k_ra8_sdsr_all.
The SDRAMC register block is mapped.
Postcondition
On k_ra8_ok (SDSR & mask) == 0.
On timeout the SDRAMC is left untouched.
Note
Not thread-safe.
Since
0.1.0

Definition at line 245 of file ra8_sdramc.c.

References k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_sdramc_spin_max, RA8_INTERNAL, ra8_log_error, ra8_sdramc(), s_tag, and r_sdramc_regs_t::SDSR.

Referenced by ra8_sdramc_enter_self_refresh(), ra8_sdramc_exit_self_refresh(), and ra8_sdramc_init().

◆ ra8_sdramc_deinit()

ra8_err_t ra8_sdramc_deinit ( void )
nodiscard

Tear down the SDRAM controller (disable refresh, clear SDICR).

Since
0.1.0

Definition at line 321 of file ra8_sdramc.c.

References k_ra8_ok, ra8_sdramc(), r_sdramc_regs_t::SDCCR, and r_sdramc_regs_t::SDRFEN.

◆ ra8_sdramc_enter_self_refresh()

ra8_err_t ra8_sdramc_enter_self_refresh ( void )
nodiscard

Put the external SDRAM into JEDEC self-refresh mode.

Self-refresh is the low-power retention state in which the SDRAM device drives its own internal refresh cycles from its own oscillator while the external bus is idle. This is the required state before the MCU enters Software Standby so the SDRAM contents (working set at 0x68000000) survive sleep.

Entry sequence (HUM Ch 15.3.14, Table 15.8):

  1. Confirm all SDSR status bits are clear.
  2. Disable auto-refresh (SDRFEN = 0).
  3. Assert SDSELF.SFEN = 1; the hardware issues a final auto-refresh then switches the device to self-refresh mode.
  4. Poll SDSR.SRFST until it clears, confirming the SDRAM has accepted the self-refresh command. The poll is bounded by k_ra8_sdramc_spin_max iterations (NASA P10 Rule 2).
Returns
ra8_err_t Error code.
Return values
k_ra8_okSDRAM is now in self-refresh.
k_ra8_err_invalid_stateSDSR status bits were non-zero on entry, or SDSELF.SFEN was already 1.
k_ra8_err_hw_timeoutSDSR.SRFST did not clear within k_ra8_sdramc_spin_max polls.
Precondition
SDSR.SRFST, INIST, and MRSST are all 0 (no operation in progress).
SDSELF.SFEN is 0 (not already in self-refresh).
Postcondition
On k_ra8_ok, SDSELF.SFEN is 1 (self-refresh active).
On k_ra8_ok, SDSR.SRFST is 0 (transition complete).
Note
Not thread-safe. Must be called from a context that guarantees exclusive access to the SDRAMC register block.
SDRAM contents remain valid throughout self-refresh. No DMA or CPU access to the SDRAM window (0x68000000) may occur while in self-refresh.
See also
ra8_sdramc_exit_self_refresh() Paired exit function.
ra8_sdramc_enter_stop() Deeper stop (loses refresh entirely).
Since
0.1.0
HUM:
Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606. Ch 15.3.22 "SDSR : SDRAM Status Register" p 613. Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608.
NASA Power of 10 Compliance:
  • Rule 2: SDSR poll loop bounded by k_ra8_sdramc_spin_max.
  • Rule 5: 2 precondition checks (SDSR idle, SFEN clear).

Definition at line 360 of file ra8_sdramc.c.

References internal_sdramc_wait(), k_ra8_err_invalid_state, k_ra8_ok, k_ra8_sdself_sfen, k_ra8_sdsr_all, k_ra8_sdsr_srfst, ra8_log_error, ra8_log_info, ra8_sdramc(), s_tag, r_sdramc_regs_t::SDRFEN, r_sdramc_regs_t::SDSELF, and r_sdramc_regs_t::SDSR.

◆ ra8_sdramc_enter_stop()

ra8_err_t ra8_sdramc_enter_stop ( void )
nodiscard

Disable auto-refresh for deep-sleep entry.

Since
0.1.0

Definition at line 346 of file ra8_sdramc.c.

References k_ra8_ok, ra8_sdramc(), and r_sdramc_regs_t::SDRFEN.

◆ ra8_sdramc_exit_self_refresh()

ra8_err_t ra8_sdramc_exit_self_refresh ( void )
nodiscard

Exit SDRAM self-refresh and resume normal auto-refresh operation.

Clears SDSELF.SFEN to end self-refresh. The hardware performs SDRFCR.REFW self-refresh clearing cycles before returning the device to normal auto-refresh mode. Auto-refresh is then explicitly re-enabled via SDRFEN.

Exit sequence (HUM Ch 15.3.14, Table 15.8):

  1. Confirm SDSELF.SFEN is 1 (currently in self-refresh).
  2. Confirm SDSR.SRFST is 0 (no transition in progress).
  3. Clear SDSELF.SFEN = 0; the hardware runs the clearing cycles.
  4. Poll SDSR.SRFST until it clears (recovery complete).
  5. Re-enable auto-refresh (SDRFEN = 1).
Returns
ra8_err_t Error code.
Return values
k_ra8_okSDRAM has returned to auto-refresh.
k_ra8_err_invalid_stateSDSELF.SFEN was 0 (not in self-refresh) or SDSR.SRFST was set on entry.
k_ra8_err_hw_timeoutSDSR.SRFST did not clear within k_ra8_sdramc_spin_max polls.
Precondition
SDSELF.SFEN is 1 (currently in self-refresh).
SDSR.SRFST is 0 (self-refresh entry transition is complete).
Postcondition
On k_ra8_ok, SDSELF.SFEN is 0 (self-refresh inactive).
On k_ra8_ok, SDRFEN.RFEN is 1 (auto-refresh re-enabled).
Note
Not thread-safe. Must be called before resuming any DMA or CPU access to the SDRAM window (0x68000000).
Must be called after the MCU returns from Software Standby before any access to 0x68000000 is safe.
See also
ra8_sdramc_enter_self_refresh() Paired entry function.
Since
0.1.0
HUM:
Ch 15.3.14 "SDSELF : SDRAM Self-Refresh Control Register" p 606. Ch 15.3.22 "SDSR : SDRAM Status Register" p 613. Ch 15.3.16 "SDRFEN : SDRAM Auto-Refresh Control Register" p 608.
NASA Power of 10 Compliance:
  • Rule 2: SDSR poll loop bounded by k_ra8_sdramc_spin_max.
  • Rule 5: 2 precondition checks (SFEN set, SRFST clear).

Definition at line 400 of file ra8_sdramc.c.

References internal_sdramc_wait(), k_ra8_err_invalid_state, k_ra8_ok, k_ra8_sdramc_kick, k_ra8_sdself_sfen, k_ra8_sdsr_srfst, ra8_log_error, ra8_log_info, ra8_sdramc(), s_tag, r_sdramc_regs_t::SDRFEN, r_sdramc_regs_t::SDSELF, and r_sdramc_regs_t::SDSR.

◆ ra8_sdramc_exit_stop()

ra8_err_t ra8_sdramc_exit_stop ( void )
nodiscard

Re-enable auto-refresh after wake-up.

Since
0.1.0

Definition at line 353 of file ra8_sdramc.c.

References k_ra8_ok, k_ra8_sdramc_kick, ra8_sdramc(), and r_sdramc_regs_t::SDRFEN.

◆ ra8_sdramc_get_status()

ra8_err_t ra8_sdramc_get_status ( uint8_t * out_enabled)
nodiscard

Read the refresh-enable bit as a status mask.

Parameters
[out]out_enabledNon-zero when SDRFEN is set.
Since
0.1.0

Definition at line 338 of file ra8_sdramc.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_sdramc(), s_tag, and r_sdramc_regs_t::SDRFEN.

◆ ra8_sdramc_init()

◆ ra8_sdramc_set_refresh_interval()

ra8_err_t ra8_sdramc_set_refresh_interval ( uint16_t sdrfcr)
nodiscard

Change the SDRAM auto-refresh interval at runtime.

Parameters
[in]sdrfcrNew SDRFCR value.
Since
0.1.0

Definition at line 331 of file ra8_sdramc.c.

References k_ra8_ok, ra8_sdramc(), and r_sdramc_regs_t::SDRFCR.

Variable Documentation

◆ s_sdram_bus_pins

const ra8_port_pin_t s_sdram_bus_pins[]
static

The 57 EK-RA8D2 parallel-bus pins the SDRAMC drives.

The exact MCU-pin assignments are transcribed from the EK-RA8D2 v1 User's Manual, Table 30 "SDRAM Assignments": A0-A12, BA0-BA1, DQ0-DQ31, CKE, SDCLK, DQM0-DQM3, WE, CAS, RAS, CS. Each is muxed to the external-bus function with PFS PSEL = k_ra8_psel_bus.

Note
File-scope constant; not modified at runtime.
Since
0.1.0

Definition at line 119 of file ra8_sdramc.c.

Referenced by internal_sdramc_route_pins().

◆ s_tag

const char* s_tag = "SDRAM"
static

Definition at line 40 of file ra8_sdramc.c.