-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathpsram.h
More file actions
233 lines (201 loc) · 8.9 KB
/
Copy pathpsram.h
File metadata and controls
233 lines (201 loc) · 8.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
* Copyright (c) 2026 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _HARDWARE_PSRAM_H
#define _HARDWARE_PSRAM_H
#include "pico.h"
#include "hardware/clocks.h"
#include "hardware/flash.h"
/** \file psram.h
* \defgroup pico_psram pico_psram
*
* \brief Low level PSRAM setup functions
*
* Note some of these functions are *unsafe* if you are using both cores, and the other
* is executing from flash or psram concurrently with the operation. In this case, you
* must perform your own synchronisation to make sure that no XIP accesses take
* place while running these functions. One option is to use the
* \ref multicore_lockout functions.
*
* Likewise they are *unsafe* if you have interrupt handlers or an interrupt
* vector table in flash or psram, so you must disable interrupts before calling in
* this case.
*
* The unsafe functions are:
* - \ref psram_reinitialise
* - \ref psram_detect_cs_and_size
* - \ref psram_detect_size
*/
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_PSRAM, Enable/disable assertions in the hardware_psram module, type=bool, default=0, group=hardware_psram
#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_PSRAM
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_PSRAM 0
#endif
// PICO_CONFIG: PICO_PSRAM_SIZE_BYTES, size of psram in bytes, type=int, default=Usually provided via board header if psram is present, group=hardware_psram
// PICO_CONFIG: PICO_PSRAM_CS_PIN, chip select pin for psram, type=int, default=Usually provided via board header if psram is present, group=hardware_psram
// PICO_CONFIG: PICO_AUTO_DETECT_PSRAM, automatically detect if psram is present, type=bool, default=0, group=hardware_psram
#ifndef PICO_AUTO_DETECT_PSRAM
#define PICO_AUTO_DETECT_PSRAM 0
#endif
// PICO_CONFIG: PICO_AUTO_DETECT_PSRAM_SIZE, automatically detect psram size, type=bool, default=PICO_AUTO_DETECT_PSRAM, group=hardware_psram
#ifndef PICO_AUTO_DETECT_PSRAM_SIZE
#define PICO_AUTO_DETECT_PSRAM_SIZE PICO_AUTO_DETECT_PSRAM
#endif
// PICO_CONFIG: PICO_AUTO_DETECT_PSRAM_CS, automatically detect psram chip select pin, type=bool, default=PICO_AUTO_DETECT_PSRAM, group=hardware_psram
#ifndef PICO_AUTO_DETECT_PSRAM_CS
#define PICO_AUTO_DETECT_PSRAM_CS PICO_AUTO_DETECT_PSRAM
#elif PICO_AUTO_DETECT_PSRAM_CS && !PICO_AUTO_DETECT_PSRAM_SIZE
#error "PICO_AUTO_DETECT_PSRAM_SIZE must be set to use PICO_AUTO_DETECT_PSRAM_CS"
#endif
// PICO_CONFIG: PICO_AUTO_DETECT_PSRAM_CS_SKIP_DEFAULTS, skip default GPIOs when auto-detecting psram chip select pin, type=bool, default=PICO_AUTO_DETECT_PSRAM_CS, group=hardware_psram
#ifndef PICO_AUTO_DETECT_PSRAM_CS_SKIP_DEFAULTS
#define PICO_AUTO_DETECT_PSRAM_CS_SKIP_DEFAULTS PICO_AUTO_DETECT_PSRAM_CS
#endif
// PICO_CONFIG: PICO_DEFAULT_PSRAM_ID, Default ID of psram used for auto-detection, type=int, default=0x5D, group=hardware_psram
#ifndef PICO_DEFAULT_PSRAM_ID
#define PICO_DEFAULT_PSRAM_ID 0x5D
#endif
// PICO_CONFIG: PICO_DEFAULT_PSRAM_MAX_FREQ, Default max frequency of psram, type=int, default=133 * MHZ, group=hardware_psram
#ifndef PICO_DEFAULT_PSRAM_MAX_FREQ
#define PICO_DEFAULT_PSRAM_MAX_FREQ 133 * MHZ
#endif
// PICO_CONFIG: PICO_DEFAULT_PSRAM_MAX_SELECT, Default max select time of psram in ns, type=int, default=8000, group=hardware_psram
#ifndef PICO_DEFAULT_PSRAM_MAX_SELECT
#define PICO_DEFAULT_PSRAM_MAX_SELECT 8000
#endif
// PICO_CONFIG: PICO_DEFAULT_PSRAM_MIN_DESELECT, Default min deselect time of psram in ns, type=int, default=18, group=hardware_psram
#ifndef PICO_DEFAULT_PSRAM_MIN_DESELECT
#define PICO_DEFAULT_PSRAM_MIN_DESELECT 18
#endif
// PICO_CONFIG: PICO_RUNTIME_SKIP_INIT_PSRAM, Skip calling of `runtime_init_psram` function during runtime init, type=bool, default=0, group=pico_runtime_init
// PICO_CONFIG: PICO_RUNTIME_NO_INIT_PSRAM, Do not include SDK implementation of `runtime_init_psram` function, type=bool, default=0, group=pico_runtime_init
#ifndef PICO_RUNTIME_INIT_PSRAM
#define PICO_RUNTIME_INIT_PSRAM "11080"
#endif
#ifndef PICO_RUNTIME_SKIP_INIT_PSRAM
#define PICO_RUNTIME_SKIP_INIT_PSRAM 0
#endif
#ifndef PICO_RUNTIME_NO_INIT_PSRAM
#define PICO_RUNTIME_NO_INIT_PSRAM 0
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*! \brief Check if PSRAM is available and initialised
* \ingroup hardware_psram
*
* \return true if PSRAM is available and initialised, false otherwise
*/
bool psram_is_available(void);
/*! \brief Get the size of the PSRAM
* \ingroup hardware_psram
*
* Retrieve the size of the PSRAM, either from PICO_PSRAM_SIZE_BYTES,
* flash_devinfo, or auto-detection.
*
* \return size of PSRAM in bytes, or 0 if none
*/
size_t psram_get_size(void);
/*! \brief Check if an address is in available PSRAM
* \ingroup hardware_psram
*
* \return true if the address is in available PSRAM, false otherwise
*/
bool psram_check_address(void* addr);
/*! \brief Detect PSRAM size
* \ingroup hardware_psram
*
* This will read the ID of the PSRAM chip and return the size based on the ID.
*
* You must configure the GPIO function for the CS pin before calling this function,
* and should also configure the CS GPIO in flash_devinfo to prevent toggling of the
* previously configured GPIO (usually 0, so prints invalid characters to default UART).
*
* \return size of PSRAM, or 0 if none found
*/
size_t psram_detect_size(void);
/*! \brief Detect PSRAM chip select pin and size
* \ingroup hardware_psram
*
* This runs \ref psram_detect_size() for each CS GPIO in the array in turn,
* and returns the size as soon as a PSRAM chip is detected.
*
* This will setup the CS GPIO using flash_devinfo if PSRAM is found.
*
* \param cs_gpios Array of CS GPIOs to try
* \param num Number of CS GPIOs in the array
* \return size of PSRAM, or 0 if none found
*/
size_t psram_detect_cs_and_size(uint8_t *cs_gpios, size_t num);
/*! \brief Configure PSRAM timing parameters
* \ingroup hardware_psram
*
* This will calculate and set the PSRAM timing parameters based on the given values.
*
* Note: This will also implement the workaround for RP2350-E14 if PICO_RP2350_A2_SUPPORTED is set.
*
* \param max_psram_freq Maximum frequency of PSRAM
* \param max_select_ns Maximum select time in ns
* \param min_deselect_ns Minimum deselect time in ns
* \return PICO_OK on success, PICO_ERROR_INVALID_ARG if unable to calculate valid parameters
*/
int psram_configure_params(uint32_t max_psram_freq, uint32_t max_select_ns, uint32_t min_deselect_ns);
/*! \brief Explicitly set PSRAM timing parameters
* \ingroup hardware_psram
*
* This will explicitly set the PSRAM timing parameters to the given values.
*
* This may be necessary if the parameters calculated by \ref psram_configure_params are not suitable.
*
* \param divisor Divisor for PSRAM clock
* \param rxdelay RX delay for PSRAM clock
* \param max_select Maximum select time in multiples of 64 system clocks
* \param min_deselect Minimum deselect time in system clock cycles - ceil(divisor / 2)
* \return PICO_OK on success, PICO_ERROR_INVALID_ARG if any of the parameters are invalid
*/
int psram_set_params(uint32_t divisor, uint32_t rxdelay, uint32_t max_select, uint32_t min_deselect);
/*! \brief Re-initialise PSRAM
* \ingroup hardware_psram
*
* This will re-initialise the PSRAM with the parameters set by \ref psram_configure_params.
*
* This calls \ref flash_start_xip internally, so will reset any QSPI pads changes you have made.
*
* \return PICO_OK on success, PICO_ERROR_PRECONDITION_NOT_MET if the PSRAM size is not set in
* flash_devinfo or the PSRAM parameters are not set by \ref psram_configure_params or \ref psram_set_params
*/
int psram_reinitialise(void);
/*! \brief Convert PSRAM EID to size
* \ingroup hardware_psram
*
* This will convert the PSRAM EID to the size in bytes.
*
* This is not intended to be called by the user, but is provided as a weak function so it can
* be overridden if other PSRAM chips are used that have different EID to size mapping.
*
* This is used by \ref psram_detect_size to check the KGD and convert the EID to the size.
*
* \param kgd Known Good Die
* \param eid EID
* \return size of PSRAM in bytes, or 0 if the KGD/EID is not recognised
*/
size_t psram_eid_to_size(uint8_t kgd, uint8_t eid);
/*! \brief Provide a static PSRAM allocation, or malloc if PSRAM is not available
* \ingroup hardware_psram
*
* This will allocate a static buffer in PSRAM and if available use that, otherwise it will use the heap.
*
* This will fail to compile if PICO_PSRAM_SIZE_BYTES is not set
*/
#define psram_or_malloc(group, type, var, size) static type __psram_uninitialised(group) var##_psram[size]; type* var; if (psram_check_address(var##_psram + size)) { var = (type*)var##_psram; } else { var = (type*)malloc(size * sizeof(type)); }
/*! \brief Free a buffer if it is not in PSRAM
* \ingroup hardware_psram
*
* This will free the buffer from \ref psram_or_malloc if it was created by malloc
*/
#define psram_or_free(var) if (!psram_check_address(var##_psram)) { free(var); }
#ifdef __cplusplus
}
#endif
#endif // _HARDWARE_PSRAM_H