Mistake on this page?
Report an issue in GitHub or email us
OSPI.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2020 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef MBED_OSPI_H
18 #define MBED_OSPI_H
19 
20 #include "platform/platform.h"
21 
22 #if DEVICE_OSPI || defined(DOXYGEN_ONLY)
23 
24 #include "hal/ospi_api.h"
25 #include "platform/PlatformMutex.h"
26 #include "platform/SingletonPtr.h"
27 #include "platform/NonCopyable.h"
28 
29 #define ONE_MHZ 1000000
30 
31 #define OSPI_NO_INST (-1)
32 
33 namespace mbed {
34 /** \defgroup drivers-public-api-spi SPI
35  * \ingroup drivers-public-api
36  */
37 
38 /**
39  * \defgroup drivers_OSPI OSPI class
40  * \ingroup drivers-public-api-spi
41  * @{
42  */
43 
44 /** Type representing a OSPI instruction
45  */
46 typedef int ospi_inst_t;
47 
48 /** A OSPI Driver, used for communicating with OSPI slave devices
49  *
50  * The default format is set to OCTO-SPI(1-1-1), and a clock frequency of 1MHz
51  * Most OSPI devices will also require Chip Select which is indicated by ssel.
52  *
53  * @note Synchronization level: Thread safe
54  *
55  * Example:
56  * @code
57  * // Write 4 byte array to a OSPI slave, and read the response, note that each device will have its specific read/write/alt values defined
58  *
59  * #include "mbed.h"
60  *
61  * #define CMD_WRITE 0x02
62  * #define CMD_READ 0x03
63  * #define ADDRESS 0x1000
64  *
65  * // hardware ssel (where applicable)
66  * OSPI ospi_device(OSPI_FLASH1_IO0, OSPI_FLASH1_IO1, OSPI_FLASH1_IO2, OSPI_FLASH1_IO3, OSPI_FLASH1_IO4, OSPI_FLASH1_IO5, OSPI_FLASH1_IO6,
67  * OSPI_FLASH1_SCK, OSPI_FLASH1_CSN, OSPI_FLASH1_DQS); // io0, io1, io2, io3, io4, io5, io6, io7, sclk, ssel, dqs
68  *
69  *
70  * int main() {
71  * char tx_buf[] = { 0x11, 0x22, 0x33, 0x44 };
72  * char rx_buf[4];
73  * int buf_len = sizeof(tx_buf);
74  *
75  * ospi_status_t result = ospi_device.write(CMD_WRITE, 0, ADDRESS, tx_buf, &buf_len);
76  * if (result != OSPI_STATUS_OK) {
77  * printf("Write failed");
78  * }
79  * result = ospi_device.read(CMD_READ, 0, ADDRESS, rx_buf, &buf_len);
80  * if (result != OSPI_STATUS_OK) {
81  * printf("Read failed");
82  * }
83  *
84  * }
85  * @endcode
86  */
87 class OSPI : private NonCopyable<OSPI> {
88 
89 public:
90 
91  /** Create a OSPI master connected to the specified pins
92  *
93  * io0-io3 is used to specify the Pins used for Quad SPI mode
94  *
95  * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
96  * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
97  * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
98  * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
99  * @param io4 5th IO pin used for sending/receiving data during data phase of a transaction
100  * @param io5 6th IO pin used for sending/receiving data during data phase of a transaction
101  * @param io6 7th IO pin used for sending/receiving data during data phase of a transaction
102  * @param io7 8th IO pin used for sending/receiving data during data phase of a transaction
103  * @param sclk OSPI Clock pin
104  * @param ssel OSPI chip select pin
105  * @param dqs OSPI dqs pin
106  * @param mode Clock polarity and phase mode (0 - 3) of SPI
107  * (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
108  *
109  */
110  OSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7,
111  PinName sclk, PinName ssel = NC, PinName dqs = NC, int mode = 0);
112 
113  /** Create a OSPI master connected to the specified pins
114  *
115  * io0-io3 is used to specify the Pins used for Quad SPI mode
116  *
117  * @param pinmap reference to structure which holds static pinmap
118  * @param mode Clock polarity and phase mode (0 - 3) of SPI
119  * (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
120  *
121  */
122  OSPI(const ospi_pinmap_t &pinmap, int mode = 0);
123  OSPI(const ospi_pinmap_t &&, int = 0) = delete; // prevent passing of temporary objects
124 
125  virtual ~OSPI()
126  {
127  }
128 
129  /** Configure the data transmission format
130  *
131  * @param inst_width Bus width used by instruction phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
132  * @param inst_size Size in bits used by instruction phase
133  * @param address_width Bus width used by address phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
134  * @param address_size Size in bits used by address phase(Valid values are OSPI_CFG_ADDR_SIZE_8, OSPI_CFG_ADDR_SIZE_16, OSPI_CFG_ADDR_SIZE_24, OSPI_CFG_ADDR_SIZE_32)
135  * @param alt_width Bus width used by alt phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
136  * @param alt_size Size in bits used by alt phase (must be a multiple of the number of bus lines indicated in alt_width)
137  * @param data_width Bus width used by data phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
138  * @param dummy_cycles Number of dummy clock cycles to be used after alt phase
139  *
140  */
141  ospi_status_t configure_format(ospi_bus_width_t inst_width,
142  ospi_inst_size_t inst_size,
143  ospi_bus_width_t address_width,
144  ospi_address_size_t address_size,
145  ospi_bus_width_t alt_width,
146  ospi_alt_size_t alt_size,
147  ospi_bus_width_t data_width,
148  int dummy_cycles);
149 
150  /** Set the ospi bus clock frequency
151  *
152  * @param hz SCLK frequency in hz (default = 1MHz)
153  * @returns
154  * Returns OSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed
155  */
156  ospi_status_t set_frequency(int hz = ONE_MHZ);
157 
158  /** Read from OSPI peripheral with the preset read_instruction and alt_value
159  *
160  * @param address Address to be accessed in OSPI peripheral
161  * @param rx_buffer Buffer for data to be read from the peripheral
162  * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
163  *
164  * @returns
165  * Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
166  */
167  ospi_status_t read(int address, char *rx_buffer, size_t *rx_length);
168 
169  /** Write to OSPI peripheral using custom write instruction
170  *
171  * @param address Address to be accessed in OSPI peripheral
172  * @param tx_buffer Buffer containing data to be sent to peripheral
173  * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
174  *
175  * @returns
176  * Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
177  */
178  ospi_status_t write(int address, const char *tx_buffer, size_t *tx_length);
179 
180  /** Read from OSPI peripheral using custom read instruction, alt values
181  *
182  * @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
183  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
184  * @param address Address to be accessed in OSPI peripheral
185  * @param rx_buffer Buffer for data to be read from the peripheral
186  * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
187  *
188  * @returns
189  * Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
190  */
191  ospi_status_t read(ospi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length);
192 
193  /** Write to OSPI peripheral using custom write instruction, alt values
194  *
195  * @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
196  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
197  * @param address Address to be accessed in OSPI peripheral
198  * @param tx_buffer Buffer containing data to be sent to peripheral
199  * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
200  *
201  * @returns
202  * Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
203  */
204  ospi_status_t write(ospi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length);
205 
206  /** Perform a transaction to write to an address(a control register) and get the status results
207  *
208  * @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
209  * @param address Some instruction might require address. Use -1 if no address
210  * @param tx_buffer Buffer containing data to be sent to peripheral
211  * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
212  * @param rx_buffer Buffer for data to be read from the peripheral
213  * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
214  *
215  * @returns
216  * Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
217  */
218  ospi_status_t command_transfer(ospi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
219 
220 #if !defined(DOXYGEN_ONLY)
221 protected:
222  /** Acquire exclusive access to this SPI bus
223  */
224  virtual void lock(void);
225 
226  /** Release exclusive access to this SPI bus
227  */
228  virtual void unlock(void);
229 
230  ospi_t _ospi;
231 
232  static SingletonPtr<PlatformMutex> _mutex;
233  ospi_bus_width_t _inst_width; //Bus width for Instruction phase
234  ospi_inst_size_t _inst_size; //Instruction Size
235  ospi_bus_width_t _address_width; //Bus width for Address phase
236  ospi_address_size_t _address_size;
237  ospi_bus_width_t _alt_width; //Bus width for Alt phase
238  ospi_alt_size_t _alt_size;
239  ospi_bus_width_t _data_width; //Bus width for Data phase
240  ospi_command_t _ospi_command; //OSPI Hal command struct
241  unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
242  int _hz; //Bus Frequency
243  int _mode; //SPI mode
244  bool _initialized;
245  PinName _ospi_io0, _ospi_io1, _ospi_io2, _ospi_io3, _ospi_io4, _ospi_io5, _ospi_io6, _ospi_io7, _ospi_clk, _ospi_cs, _ospi_dqs; //IO lines, clock, chip select and dqs
246  const ospi_pinmap_t *_static_pinmap;
247  bool (OSPI::* _init_func)(void);
248 
249 private:
250  bool _initialize();
251  bool _initialize_direct();
252 
253  /*
254  * This function builds the ospi command struct to be send to Hal
255  */
256  inline void _build_ospi_command(ospi_inst_t instruction, int address, int alt);
257 #endif
258 };
259 
260 /** @}*/
261 
262 } // namespace mbed
263 
264 #endif
265 
266 #endif
ospi_status_t configure_format(ospi_bus_width_t inst_width, ospi_inst_size_t inst_size, ospi_bus_width_t address_width, ospi_address_size_t address_size, ospi_bus_width_t alt_width, ospi_alt_size_t alt_size, ospi_bus_width_t data_width, int dummy_cycles)
Configure the data transmission format.
ospi_status_t command_transfer(ospi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
Perform a transaction to write to an address(a control register) and get the status results...
A OSPI Driver, used for communicating with OSPI slave devices.
Definition: OSPI.h:87
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
ospi_status_t set_frequency(int hz=1000000)
Set the ospi bus clock frequency.
ospi_status_t read(int address, char *rx_buffer, size_t *rx_length)
Read from OSPI peripheral with the preset read_instruction and alt_value.
ospi_status_t write(int address, const char *tx_buffer, size_t *tx_length)
Write to OSPI peripheral using custom write instruction.
OSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7, PinName sclk, PinName ssel=NC, PinName dqs=NC, int mode=0)
Create a OSPI master connected to the specified pins.
int ospi_inst_t
Type representing a OSPI instruction.
Definition: OSPI.h:46
Definition: ATHandler.h:46
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.