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  lock();
121  qspi_free(&_qspi);
122  unlock();
123  }
124 
125  /** Configure the data transmission format
126  *
127  * @param inst_width Bus width used by instruction phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
128  * @param address_width Bus width used by address phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
129  * @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)
130  * @param alt_width Bus width used by alt phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
131  * @param alt_size Size in bits used by alt phase (must be a multiple of the number of bus lines indicated in alt_width)
132  * @param data_width Bus width used by data phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
133  * @param dummy_cycles Number of dummy clock cycles to be used after alt phase
134  *
135  */
137  qspi_bus_width_t address_width,
138  qspi_address_size_t address_size,
139  qspi_bus_width_t alt_width,
140  qspi_alt_size_t alt_size,
141  qspi_bus_width_t data_width,
142  int dummy_cycles);
143 
144  /** Set the qspi bus clock frequency
145  *
146  * @param hz SCLK frequency in hz (default = 1MHz)
147  * @returns
148  * Returns QSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed
149  */
150  qspi_status_t set_frequency(int hz = ONE_MHZ);
151 
152  /** Read from QSPI peripheral with the preset read_instruction and alt_value
153  *
154  * @param address Address to be accessed in QSPI peripheral
155  * @param rx_buffer Buffer for data to be read from the peripheral
156  * @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
157  *
158  * @returns
159  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
160  */
161  qspi_status_t read(int address, char *rx_buffer, size_t *rx_length);
162 
163  /** Write to QSPI peripheral using custom write instruction
164  *
165  * @param address Address to be accessed in QSPI peripheral
166  * @param tx_buffer Buffer containing data to be sent to peripheral
167  * @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
168  *
169  * @returns
170  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
171  */
172  qspi_status_t write(int address, const char *tx_buffer, size_t *tx_length);
173 
174  /** Read from QSPI peripheral using custom read instruction, alt values
175  *
176  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
177  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
178  * @param address Address to be accessed in QSPI peripheral
179  * @param rx_buffer Buffer for data to be read from the peripheral
180  * @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
181  *
182  * @returns
183  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
184  */
185  qspi_status_t read(qspi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length);
186 
187  /** Write to QSPI peripheral using custom write instruction, alt values
188  *
189  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
190  * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
191  * @param address Address to be accessed in QSPI peripheral
192  * @param tx_buffer Buffer containing data to be sent to peripheral
193  * @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
194  *
195  * @returns
196  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
197  */
198  qspi_status_t write(qspi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length);
199 
200  /** Perform a transaction to write to an address(a control register) and get the status results
201  *
202  * @param instruction Instruction value to be used in instruction phase. Use QSPI_NO_INST to skip the instruction phase
203  * @param address Some instruction might require address. Use -1 if no address
204  * @param tx_buffer Buffer containing data to be sent to peripheral
205  * @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
206  * @param rx_buffer Buffer for data to be read from the peripheral
207  * @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
208  *
209  * @returns
210  * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads.
211  */
212  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);
213 
214 #if !defined(DOXYGEN_ONLY)
215 protected:
216  /** Acquire exclusive access to this SPI bus
217  */
218  virtual void lock(void);
219 
220  /** Release exclusive access to this SPI bus
221  */
222  virtual void unlock(void);
223 
224  qspi_t _qspi;
225 
226  bool acquire(void);
227  static QSPI *_owner;
228  static SingletonPtr<PlatformMutex> _mutex;
229  qspi_bus_width_t _inst_width; //Bus width for Instruction phase
230  qspi_bus_width_t _address_width; //Bus width for Address phase
231  qspi_address_size_t _address_size;
232  qspi_bus_width_t _alt_width; //Bus width for Alt phase
233  qspi_alt_size_t _alt_size;
234  qspi_bus_width_t _data_width; //Bus width for Data phase
235  qspi_command_t _qspi_command; //QSPI Hal command struct
236  unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
237  int _hz; //Bus Frequency
238  int _mode; //SPI mode
239  bool _initialized;
240  PinName _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs; //IO lines, clock and chip select
241  const qspi_pinmap_t *_static_pinmap;
242  bool (QSPI::* _init_func)(void);
243 
244 private:
245  /* Private acquire function without locking/unlocking
246  * Implemented in order to avoid duplicate locking and boost performance
247  */
248  bool _acquire(void);
249  bool _initialize();
250  bool _initialize_direct();
251 
252  /*
253  * This function builds the qspi command struct to be send to Hal
254  */
255  inline void _build_qspi_command(qspi_inst_t instruction, int address, int alt);
256 #endif
257 };
258 
259 /** @}*/
260 
261 } // namespace mbed
262 
263 #endif
264 
265 #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:162
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.
Definition: ATHandler.h:46
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.
qspi_status_t qspi_free(qspi_t *obj)
Deinitilize QSPI peripheral.
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.