Skip to main content

esp_hal/soc/esp32s2/
mod.rs

1//! # SOC (System-on-Chip) module (ESP32-S2)
2//!
3//! ## Overview
4//!
5//! The `SOC` module provides access, functions and structures that are useful
6//! for interacting with various system-related peripherals on `ESP32-S2` chip.
7
8crate::unstable_module! {
9    pub mod clocks;
10    pub mod trng;
11    pub mod lp_core;
12}
13pub mod gpio;
14pub(crate) mod regi2c;
15
16pub(crate) use esp32s2 as pac;
17
18#[cfg(i2s_driver_supported)]
19#[cfg_attr(not(feature = "unstable"), allow(unused))]
20pub(crate) fn i2s_sclk_frequency() -> u32 {
21    // I2S uses the 160 MHz PLL tap, derived from either supported PLL frequency.
22    match clocks::pll_clk_frequency() {
23        320_000_000 => 320_000_000 / 2,
24        480_000_000 => 480_000_000 / 3,
25        _ => unreachable!(),
26    }
27}
28
29/// Write back a specific range of data in the cache.
30#[doc(hidden)]
31#[unsafe(link_section = ".rwtext")]
32pub unsafe fn cache_writeback_addr(addr: u32, size: u32) {
33    unsafe extern "C" {
34        fn Cache_WriteBack_Addr(addr: u32, size: u32);
35    }
36    unsafe {
37        Cache_WriteBack_Addr(addr, size);
38    }
39}
40
41/// Invalidate a specific range of addresses in the cache.
42#[doc(hidden)]
43#[unsafe(link_section = ".rwtext")]
44pub unsafe fn cache_invalidate_addr(addr: u32, size: u32) {
45    unsafe extern "C" {
46        fn Cache_Invalidate_Addr(addr: u32, size: u32);
47    }
48    unsafe {
49        Cache_Invalidate_Addr(addr, size);
50    }
51}
52
53// Byte values (not ROM enum indices) to let DMA alignment code use these directly. The ROM calls in
54// configure_cpu_caches will convert to the expected enum index.
55pub(crate) const CONFIG_INSTRUCTION_CACHE_LINE_SIZE: usize = cfg_select! {
56    instruction_cache_line_size_16b => 16,
57    instruction_cache_line_size_32b => 32,
58};
59
60pub(crate) const CONFIG_DATA_CACHE_LINE_SIZE: usize = cfg_select! {
61    data_cache_line_size_16b => 16,
62    data_cache_line_size_32b => 32,
63};
64
65pub(crate) const CONFIG_INSTRUCTION_CACHE_SIZE: usize = cfg_select! {
66    instruction_cache_size_8kb => 0,
67    instruction_cache_size_16kb => 1,
68};
69pub(crate) const CONFIG_DATA_CACHE_SIZE: usize =
70    cfg_select! {
71        data_cache_size_0kb => 0, // doesn't matter according to esp-idf
72        data_cache_size_8kb => 0,
73        data_cache_size_16kb => 1,
74    };
75
76#[crate::ram]
77pub(crate) unsafe fn configure_cpu_caches() {
78    // Set up caches. Doesn't work when put in `configure_cpu_caches`.
79    unsafe extern "C" {
80        /// Invalidate all cache items in ICache.
81        fn Cache_Invalidate_ICache_All();
82
83        /// Set ICache modes: cache size, associate ways and cache line size.
84        ///
85        /// @param cache_size_t cache_size : the cache size, can be CACHE_SIZE_HALF and
86        /// CACHE_SIZE_FULL
87        ///
88        /// @param cache_ways_t ways : the associate ways of cache, can only be CACHE_4WAYS_ASSOC
89        ///
90        /// @param cache_line_size_t cache_line_size : the cache line size, can be
91        /// CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B
92        fn Cache_Set_ICache_Mode(cache_size: u32, ways: u32, cache_line_size: u32);
93
94        /// Resume ICache access for the cpu.
95        ///
96        /// @param  uint32_t autoload : ICache will preload then.
97        fn Cache_Resume_ICache(autoload: u32);
98
99        /// Allocate memory to used by ICache and DCache.
100        ///
101        /// [`sram0_layout`]: u32 the usage of first 8KB internal memory block,
102        /// can be CACHE_MEMORY_INVALID,
103        /// CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH,
104        /// CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH
105        /// [`sram1_layout`]: the usage of second 8KB internal memory block,
106        /// [`sram2_layout`]: the usage of third 8KB internal memory block
107        /// [`sram3_layout`]: the usage of forth 8KB internal memory block
108        fn Cache_Allocate_SRAM(
109            sram0_layout: u32,
110            sram1_layout: u32,
111            sram2_layout: u32,
112            sram3_layout: u32,
113        );
114
115        /// Set DCache modes: cache size, associate ways and cache line size.
116        ///
117        /// [`cache_size`]: u32 the cache size, can be CACHE_SIZE_HALF and CACHE_SIZE_FULL
118        /// [`ways`]: u32 the associate ways of cache, can only be CACHE_4WAYS_ASSOC
119        /// [`cache_line_size`]: u32 the cache line size, can be CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B
120        fn Cache_Set_DCache_Mode(cache_size: u32, ways: u32, cache_line_size: u32);
121
122        /// Invalidate all cache items in DCache.
123        fn Cache_Invalidate_DCache_All();
124
125        /// Enable DCache access for the cpu.
126        ///
127        /// @param  uint32_t autoload : DCache will preload then.
128        fn Cache_Enable_DCache(autoload: u32);
129    }
130
131    const CACHE_4WAYS_ASSOC: u32 = 0;
132
133    #[derive(Clone, Copy, Debug)]
134    enum CacheLayout {
135        Invalid    = 0,
136        ICacheLow  = 1 << 0,
137        ICacheHigh = 1 << 1,
138        DCacheLow  = 1 << 2,
139        DCacheHigh = 1 << 3,
140    }
141
142    let mut sram = [
143        CacheLayout::ICacheLow,
144        CacheLayout::Invalid,
145        CacheLayout::Invalid,
146        CacheLayout::Invalid,
147    ];
148    let mut idx = 1;
149
150    if cfg!(instruction_cache_size_16kb) {
151        sram[idx] = CacheLayout::ICacheHigh;
152        idx += 1;
153    }
154
155    if !cfg!(data_cache_size_0kb) {
156        sram[idx] = CacheLayout::DCacheLow;
157        idx += 1;
158    }
159    if cfg!(data_cache_size_16kb) {
160        sram[idx] = CacheLayout::DCacheHigh;
161    }
162
163    unsafe {
164        Cache_Allocate_SRAM(
165            sram[0] as u32,
166            sram[1] as u32,
167            sram[2] as u32,
168            sram[3] as u32,
169        );
170    }
171
172    unsafe {
173        // Unlike S3 code, Cache_Set_(I/D)Cache_Mode takes a cache_line_size_t enum
174        // (CACHE_LINE_SIZE_16B=0, CACHE_LINE_SIZE_32B=1) rather than the size in bytes.
175        Cache_Set_ICache_Mode(
176            CONFIG_INSTRUCTION_CACHE_SIZE as u32,
177            CACHE_4WAYS_ASSOC,
178            match CONFIG_INSTRUCTION_CACHE_LINE_SIZE {
179                16 => 0,
180                32 => 1,
181                _ => unreachable!(),
182            },
183        );
184        Cache_Invalidate_ICache_All();
185        Cache_Resume_ICache(0);
186
187        Cache_Set_DCache_Mode(
188            CONFIG_DATA_CACHE_SIZE as u32,
189            CACHE_4WAYS_ASSOC,
190            match CONFIG_DATA_CACHE_LINE_SIZE {
191                16 => 0,
192                32 => 1,
193                _ => unreachable!(),
194            },
195        );
196        Cache_Invalidate_DCache_All();
197        Cache_Enable_DCache(0);
198    }
199}
200
201pub(crate) fn pre_init() {}