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