Mistake on this page?
Report an issue in GitHub or email us
QSPI.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2018 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_QSPI_H
18 #define MBED_QSPI_H
19 
20 #include "platform/platform.h"
21 
22 #if DEVICE_QSPI || defined(DOXYGEN_ONLY)
23 
24 #include "hal/qspi_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 QSPI_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_QSPI QSPI class
40  * \ingroup drivers-public-api-spi
41  * @{
42  */
43 
44 /** Type representing a QSPI instruction
45  */
46 typedef int qspi_inst_t;
47 
48 /** A QSPI Driver, used for communicating with QSPI slave devices
49  *
50  * The default format is set to Quad-SPI(1-1-1), and a clock frequency of 1MHz
51  * Most QSPI 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 QSPI 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  * QSPI qspi_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, QSPI_FLASH1_SCK, QSPI_FLASH1_CSN); // io0, io1, io2, io3, sclk, ssel
67  *
68  *
69  * int main() {
70  * char tx_buf[] = { 0x11, 0x22, 0x33, 0x44 };
71  * char rx_buf[4];
72  * int buf_len = sizeof(tx_buf);
73  *
74  * qspi_status_t result = qspi_device.write(CMD_WRITE, 0, ADDRESS, tx_buf, &buf_len);
75  * if (result != QSPI_STATUS_OK) {
76  * printf("Write failed");
77  * }
78  * result = qspi_device.read(CMD_READ, 0, ADDRESS, rx_buf, &buf_len);
79  * if (result != QSPI_STATUS_OK) {
80  * printf("Read failed");
81  * }
82  *
83  * }
84  * @endcode
85  */
86 class QSPI : private NonCopyable<QSPI> {
87 
88 public:
89 
90  /** Create a QSPI master connected to the specified pins
91  *
92  * io0-io3 is used to specify the Pins used for Quad SPI mode
93  *
94  * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
95  * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
96  * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
97  * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
98  * @param sclk QSPI Clock pin
99  * @param ssel QSPI chip select pin
100  * @param mode Clock polarity and phase mode (0 - 3) of SPI
101  * (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
102  *
103  */
104  QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel = NC, int mode = 0);
105 
106  /** Create a QSPI master connected to the specified pins
107  *
108  * io0-io3 is used to specify the Pins used for Quad SPI mode
109  *
110  * @param pinmap reference to structure which holds static pinmap
111  * @param mode Clock polarity and phase mode (0 - 3) of SPI
112  * (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
113  *
114  */
115  QSPI(const qspi_pinmap_t &pinmap, int mode = 0);
116  QSPI(const qspi_pinmap_t &&, int = 0) = delete; // prevent passing of temporary objects
117 
118  virtual ~QSPI()
119  {
120  }
121 
122  /** Configure the data transmission format
123  *
124  * @param inst_width Bus width used by instruction phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
125  * @param address_width Bus width used by address phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
126  * @param address_size Size in bits used by address phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32)
127  * @param alt_width Bus width used by alt phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
128  * @param alt_size Size in bits used by alt phase (must be a multiple of the number of bus lines indicated in alt_width)
129  * @param data_width Bus width used by data phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
130  * @param dummy_cycles Number of dummy clock cycles to be used after alt phase
131  *
132  */
134  qspi_bus_width_t address_width,
135  qspi_address_size_t address_size,
136  qspi_bus_width_t alt_width,
137  qspi_alt_size_t alt_size,
138  qspi_bus_width_t data_width,
139  int dummy_cycles);
140 
141  /** Set the qspi bus clock frequency
142  *
143  * @param hz SCLK frequency in hz (default = 1MHz)
144  * @returns
145  * Returns QSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed
146  */
147  qspi_status_t set_frequency(int hz = ONE_MHZ);
148 
149  /** Read from QSPI peripheral with the preset read_instruction and alt_value
150  *
151  * @param address Address to be accessed in QSPI peripheral
152  * @param rx_buffer Buffer for data to be read from the peripheral
153  * @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
154  *
155  * @returns
156  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
157  */
158  qspi_status_t read(int address, char *rx_buffer, size_t *rx_length);
159 
160  /** Write to QSPI peripheral using custom write instruction
161  *
162  * @param address Address to be accessed in QSPI peripheral
163  * @param tx_buffer Buffer containing data to be sent to peripheral
164  * @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
165  *
166  * @returns
167  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
168  */
169  qspi_status_t write(int address, const char *tx_buffer, size_t *tx_length);
170 
171  /** Read from QSPI peripheral using custom read instruction, alt values
172  *
173  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
174  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
175  * @param address Address to be accessed in QSPI peripheral
176  * @param rx_buffer Buffer for data to be read from the peripheral
177  * @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
178  *
179  * @returns
180  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
181  */
182  qspi_status_t read(qspi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length);
183 
184  /** Write to QSPI peripheral using custom write instruction, alt values
185  *
186  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
187  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
188  * @param address Address to be accessed in QSPI peripheral
189  * @param tx_buffer Buffer containing data to be sent to peripheral
190  * @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
191  *
192  * @returns
193  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
194  */
195  qspi_status_t write(qspi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length);
196 
197  /** Perform a transaction to write to an address(a control register) and get the status results
198  *
199  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
200  * @param address Some instruction might require address. Use -1 if no address
201  * @param tx_buffer Buffer containing data to be sent to peripheral
202  * @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
203  * @param rx_buffer Buffer for data to be read from the peripheral
204  * @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
205  *
206  * @returns
207  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
208  */
209  qspi_status_t command_transfer(qspi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
210 
211 #if !defined(DOXYGEN_ONLY)
212 protected:
213  /** Acquire exclusive access to this SPI bus
214  */
215  virtual void lock(void);
216 
217  /** Release exclusive access to this SPI bus
218  */
219  virtual void unlock(void);
220 
221  qspi_t _qspi;
222 
223  bool acquire(void);
224  static QSPI *_owner;
225  static SingletonPtr<PlatformMutex> _mutex;
226  qspi_bus_width_t _inst_width; //Bus width for Instruction phase
227  qspi_bus_width_t _address_width; //Bus width for Address phase
228  qspi_address_size_t _address_size;
229  qspi_bus_width_t _alt_width; //Bus width for Alt phase
230  qspi_alt_size_t _alt_size;
231  qspi_bus_width_t _data_width; //Bus width for Data phase
232  qspi_command_t _qspi_command; //QSPI Hal command struct
233  unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
234  int _hz; //Bus Frequency
235  int _mode; //SPI mode
236  bool _initialized;
237  PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select
238  const qspi_pinmap_t *_static_pinmap;
239  bool (QSPI::* _init_func)(void);
240 
241 private:
242  /* Private acquire function without locking/unlocking
243  * Implemented in order to avoid duplicate locking and boost performance
244  */
245  bool _acquire(void);
246  bool _initialize();
247  bool _initialize_direct();
248 
249  /*
250  * This function builds the qspi command struct to be send to Hal
251  */
252  inline void _build_qspi_command(qspi_inst_t instruction, int address, int alt);
253 #endif
254 };
255 
256 /** @}*/
257 
258 } // namespace mbed
259 
260 #endif
261 
262 #endif
QSPI command.
Definition: qspi_api.h:92
QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel=NC, int mode=0)
Create a QSPI master connected to the specified pins.
qspi_status_t set_frequency(int hz=1000000)
Set the qspi bus clock frequency.
struct qspi_s qspi_t
QSPI HAL object.
Definition: qspi_api.h:40
qspi_status_t write(int address, const char *tx_buffer, size_t *tx_length)
Write to QSPI peripheral using custom write instruction.
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:169
qspi_status_t command_transfer(qspi_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...
enum qspi_address_size qspi_address_size_t
Address size in bits.
int qspi_inst_t
Type representing a QSPI instruction.
Definition: QSPI.h:46
uint8_t qspi_alt_size_t
Alternative size in bits.
Definition: qspi_api.h:79
enum qspi_bus_width qspi_bus_width_t
QSPI Bus width.
qspi_status_t read(int address, char *rx_buffer, size_t *rx_length)
Read from QSPI peripheral with the preset read_instruction and alt_value.
A QSPI Driver, used for communicating with QSPI slave devices.
Definition: QSPI.h:86
qspi_status_t configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, int dummy_cycles)
Configure the data transmission format.
enum qspi_status qspi_status_t
QSPI return status.
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.