31#define NS_TO_CYCLES_CLK(ns, clk_mhz) (((ns) * (clk_mhz) + 999) / 1000)
39#define CYCLES_TO_N_PLUS_1_VAL(cycles) ((cycles) > 0 ? (cycles) - 1 : 0)
48#define PS_TO_CYCLES(ps, clk_mhz) (((ps) * (clk_mhz) + 999999) / 1000000)
57#define CYCLES_TO_NS(cycles, clk_mhz) (((cycles) * 1000) / (clk_mhz))
67#define TIMING_OK(configured_cycles, required_ns, clk_mhz) \
68 (CYCLES_TO_NS(configured_cycles, clk_mhz) >= (required_ns))
81#define IS_ALIGNED(addr, size) (((addr) & ((size) - 1)) == 0)
89#define IS_POWER_OF_2(size) (((size) != 0) && (((size) & ((size) - 1)) == 0))
97#define IS_SEMC_ADDR(addr) ((addr) >= 0x80000000 && (addr) < 0xA0000000)
129 .address_access_time_ns = 10,
130 .chip_enable_access_ns = 10,
131 .output_enable_access_ns = 5,
132 .write_cycle_time_ns = 10,
133 .read_cycle_time_ns = 10,
134 .address_setup_time_ns = 0,
135 .address_hold_time_ns = 3,
136 .chip_select_setup_ns = 0,
137 .write_pulse_width_ns = 8,
138 .output_hold_time_ns = 3
147 .address_access_time_ns = 55,
148 .chip_enable_access_ns = 55,
149 .output_enable_access_ns = 25,
150 .write_cycle_time_ns = 55,
151 .read_cycle_time_ns = 55,
152 .address_setup_time_ns = 0,
153 .address_hold_time_ns = 5,
154 .chip_select_setup_ns = 0,
155 .write_pulse_width_ns = 45,
156 .output_hold_time_ns = 5
165 .address_access_time_ns = 70,
166 .chip_enable_access_ns = 70,
167 .output_enable_access_ns = 30,
168 .write_cycle_time_ns = 70,
169 .read_cycle_time_ns = 70,
170 .address_setup_time_ns = 0,
171 .address_hold_time_ns = 5,
172 .chip_select_setup_ns = 10,
173 .write_pulse_width_ns = 55,
174 .output_hold_time_ns = 5
248 uint8_t margin_percent,
255 float margin = 1.0f + (margin_percent / 100.0f);
264 cfg.advHoldLvl =
false;
267 cfg.cs_setup = CYCLES_TO_N_PLUS_1_VAL(
271 cfg.cs_hold_min = CYCLES_TO_N_PLUS_1_VAL(
272 NS_TO_CYCLES_CLK(10 * margin, clk_mhz)
275 cfg.addr_setup = CYCLES_TO_N_PLUS_1_VAL(
279 cfg.addr_hold = CYCLES_TO_N_PLUS_1_VAL(
283 cfg.wr_en_lo = CYCLES_TO_N_PLUS_1_VAL(
287 cfg.wr_en_hi = CYCLES_TO_N_PLUS_1_VAL(
291 cfg.rd_en_lo = CYCLES_TO_N_PLUS_1_VAL(
295 cfg.rd_en_hi = CYCLES_TO_N_PLUS_1_VAL(
299 cfg.addr_wr_hold = CYCLES_TO_N_PLUS_1_VAL(
305 cfg.cs_min_intv = CYCLES_TO_N_PLUS_1_VAL(2);
308 cfg.clkPin = clk_pin;
347inline void PrintSEMCConfig(
const SEMC_cfg_t &cfg, uint32_t clk_mhz)
349 printf(
"SEMC Configuration Details:\n");
350 printf(
"==========================\n");
355 printf(
"Mux Mode: ");
356 switch (cfg.muxMode) {
363 printf(
"\nTiming Parameters (Async Mode):\n");
364 printf(
" CS Setup: %u cycles (%u ns)\n",
365 cfg.cs_setup + 1, CYCLES_TO_NS(cfg.cs_setup + 1, clk_mhz));
366 printf(
" CS Hold: %u cycles (%u ns)\n",
367 cfg.cs_hold_min + 1, CYCLES_TO_NS(cfg.cs_hold_min + 1, clk_mhz));
368 printf(
" Address Setup: %u cycles (%u ns)\n",
369 cfg.addr_setup + 1, CYCLES_TO_NS(cfg.addr_setup + 1, clk_mhz));
370 printf(
" Address Hold: %u cycles (%u ns)\n",
371 cfg.addr_hold + 1, CYCLES_TO_NS(cfg.addr_hold + 1, clk_mhz));
372 printf(
" Write Enable Low: %u cycles (%u ns)\n",
373 cfg.wr_en_lo + 1, CYCLES_TO_NS(cfg.wr_en_lo + 1, clk_mhz));
374 printf(
" Write Enable High: %u cycles (%u ns)\n",
375 cfg.wr_en_hi + 1, CYCLES_TO_NS(cfg.wr_en_hi + 1, clk_mhz));
376 printf(
" Read Enable Low: %u cycles (%u ns)\n",
377 cfg.rd_en_lo + 1, CYCLES_TO_NS(cfg.rd_en_lo + 1, clk_mhz));
378 printf(
" Read Enable High: %u cycles (%u ns)\n",
379 cfg.rd_en_hi + 1, CYCLES_TO_NS(cfg.rd_en_hi + 1, clk_mhz));
380 printf(
" Address Write Hold: %u cycles (%u ns)\n",
381 cfg.addr_wr_hold + 1, CYCLES_TO_NS(cfg.addr_wr_hold + 1, clk_mhz));
382 printf(
" Turnaround: %u cycles (%u ns)\n",
383 cfg.turnaround, CYCLES_TO_NS(cfg.turnaround, clk_mhz));
384 printf(
" CS Min Interval: %u cycles (%u ns)\n",
385 cfg.cs_min_intv + 1, CYCLES_TO_NS(cfg.cs_min_intv + 1, clk_mhz));
388 uint32_t write_cycle = (cfg.wr_en_lo + 1) + (cfg.wr_en_hi + 1);
389 uint32_t read_cycle = (cfg.rd_en_lo + 1) + (cfg.rd_en_hi + 1);
391 printf(
"\nCalculated Timing:\n");
392 printf(
" Write Cycle: %u cycles (%u ns)\n",
393 write_cycle, CYCLES_TO_NS(write_cycle, clk_mhz));
394 printf(
" Read Cycle: %u cycles (%u ns)\n",
395 read_cycle, CYCLES_TO_NS(read_cycle, clk_mhz));
396 printf(
"==========================\n\n");
431inline bool ValidateSEMCConfig(
const SEMC_cfg_t &cfg, uint32_t base_addr, uint32_t size)
435 printf(
"Validating SEMC Configuration...\n");
438 if (!IS_ALIGNED(base_addr, size)) {
439 printf(
" ERROR: Base address 0x%08X not aligned to size 0x%08X\n",
445 if (!IS_POWER_OF_2(size)) {
446 printf(
" ERROR: Size 0x%08X is not a power of 2\n", size);
451 if (!IS_SEMC_ADDR(base_addr)) {
452 printf(
" ERROR: Base address 0x%08X not in valid SEMC range (0x80000000-0x9FFFFFFF)\n",
458 if (cfg.cs_setup == 0) {
459 printf(
" WARNING: CS setup is 0 - consider adding margin\n");
462 if (cfg.rd_en_hi < 3) {
463 printf(
" WARNING: Read enable high is very short - may not meet timing\n");
466 if (cfg.wr_en_hi < 3) {
467 printf(
" WARNING: Write enable high is very short - may not meet timing\n");
471 printf(
" Configuration validation PASSED\n");
473 printf(
" Configuration validation FAILED\n");
GPIO Pin Class.
Definition coldfire/cpu/MCF5441X/include/cpu_pins.h:44
SEMC_BusWidth_t
Data bus width configuration for SEMC interface.
Definition MIMXRT10xx/include/semc.h:491
@ Async
Asynchronous mode. Timing based on fixed delays. No clock synchronization required....
Definition MIMXRT10xx/include/semc.h:608
@ AdvMux
Advanced multiplexed mode. Enhanced multiplexing with additional control signals for complex timing.
Definition MIMXRT10xx/include/semc.h:516
@ Bus
Non-multiplexed bus mode (write only). Separate address and data buses. Reads are performed as AD-Mux...
Definition MIMXRT10xx/include/semc.h:517
@ Mux
Multiplexed address/data mode. Address and data share the same pins. Requires ADV signal to latch add...
Definition MIMXRT10xx/include/semc.h:515
@ Width_8
8-bit data bus (D[7:0]). Suitable for 8-bit memory devices or low pin-count designs.
Definition MIMXRT10xx/include/semc.h:492
@ Width_16
16-bit data bus (D[15:0]). Suitable for 16-bit memory devices. Provides 2x throughput compared to 8-b...
Definition MIMXRT10xx/include/semc.h:493
@ Burst_1
Single-beat transfer. No burst mode. Each access requires full address cycle. Use for random access o...
Definition MIMXRT10xx/include/semc.h:661
@ Width_0
No column addressing. Do not configure address pins for column mode. Use for simple SRAM/NOR Flash wi...
Definition MIMXRT10xx/include/semc.h:558
Configuration structure for SEMC (Smart External Memory Controller) interface.
Definition MIMXRT10xx/include/semc.h:799
Timing specifications for common SRAM speeds.
Definition semc_utils.h:110
uint32_t chip_enable_access_ns
tACE - CE to data valid
Definition semc_utils.h:112
uint32_t output_enable_access_ns
tOE - OE to data valid
Definition semc_utils.h:113
uint32_t read_cycle_time_ns
tRC - Read cycle time
Definition semc_utils.h:115
uint32_t address_hold_time_ns
tAH - Address hold from WE
Definition semc_utils.h:117
uint32_t chip_select_setup_ns
tCS - CS setup time
Definition semc_utils.h:118
uint32_t address_access_time_ns
tAA - Address to data valid
Definition semc_utils.h:111
uint32_t address_setup_time_ns
tAS - Address setup to WE
Definition semc_utils.h:116
uint32_t write_pulse_width_ns
tWP - WE pulse width
Definition semc_utils.h:119
uint32_t output_hold_time_ns
tOH - Data hold after OE high
Definition semc_utils.h:120
uint32_t write_cycle_time_ns
tWC - Write cycle time
Definition semc_utils.h:114