Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
QSPI.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2018 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "drivers/QSPI.h" 00019 #include "platform/mbed_critical.h" 00020 #include <string.h> 00021 00022 #if DEVICE_QSPI 00023 00024 namespace mbed { 00025 00026 QSPI *QSPI::_owner = NULL; 00027 SingletonPtr<PlatformMutex> QSPI::_mutex; 00028 00029 uint8_t convert_bus_width_to_line_count(qspi_bus_width_t width) 00030 { 00031 switch (width) { 00032 case QSPI_CFG_BUS_SINGLE: 00033 return 1; 00034 case QSPI_CFG_BUS_DUAL: 00035 return 2; 00036 case QSPI_CFG_BUS_QUAD: 00037 return 4; 00038 default: 00039 // Unrecognized bus width 00040 return 0; 00041 } 00042 } 00043 00044 QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, int mode) : _qspi() 00045 { 00046 _qspi_io0 = io0; 00047 _qspi_io1 = io1; 00048 _qspi_io2 = io2; 00049 _qspi_io3 = io3; 00050 _qspi_clk = sclk; 00051 _qspi_cs = ssel; 00052 _static_pinmap = NULL; 00053 _inst_width = QSPI_CFG_BUS_SINGLE; 00054 _address_width = QSPI_CFG_BUS_SINGLE; 00055 _address_size = QSPI_CFG_ADDR_SIZE_24; 00056 _alt_width = QSPI_CFG_BUS_SINGLE; 00057 _alt_size = 0; 00058 _data_width = QSPI_CFG_BUS_SINGLE; 00059 _num_dummy_cycles = 0; 00060 _mode = mode; 00061 _hz = ONE_MHZ; 00062 _initialized = false; 00063 _init_func = &QSPI::_initialize; 00064 00065 //Go ahead init the device here with the default config 00066 bool success = (this->*_init_func)(); 00067 MBED_ASSERT(success); 00068 } 00069 00070 QSPI::QSPI(const qspi_pinmap_t &pinmap, int mode) : _qspi() 00071 { 00072 _qspi_io0 = pinmap.data0_pin; 00073 _qspi_io1 = pinmap.data1_pin; 00074 _qspi_io2 = pinmap.data2_pin; 00075 _qspi_io3 = pinmap.data3_pin; 00076 _qspi_clk = pinmap.sclk_pin; 00077 _qspi_cs = pinmap.ssel_pin; 00078 _static_pinmap = &pinmap; 00079 _inst_width = QSPI_CFG_BUS_SINGLE; 00080 _address_width = QSPI_CFG_BUS_SINGLE; 00081 _address_size = QSPI_CFG_ADDR_SIZE_24; 00082 _alt_width = QSPI_CFG_BUS_SINGLE; 00083 _alt_size = QSPI_CFG_ALT_SIZE_8; 00084 _data_width = QSPI_CFG_BUS_SINGLE; 00085 _num_dummy_cycles = 0; 00086 _mode = mode; 00087 _hz = ONE_MHZ; 00088 _initialized = false; 00089 _init_func = &QSPI::_initialize_direct; 00090 00091 //Go ahead init the device here with the default config 00092 bool success = (this->*_init_func)(); 00093 MBED_ASSERT(success); 00094 } 00095 00096 qspi_status_t QSPI::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) 00097 { 00098 // Check that alt_size/alt_width are a valid combination 00099 uint8_t alt_lines = convert_bus_width_to_line_count(alt_width); 00100 if (alt_lines == 0) { 00101 return QSPI_STATUS_ERROR; 00102 } else if (alt_size % alt_lines != 0) { 00103 // Invalid alt size/width combination (alt size is not a multiple of the number of bus lines used to transmit it) 00104 return QSPI_STATUS_ERROR; 00105 } 00106 00107 lock(); 00108 _inst_width = inst_width; 00109 _address_width = address_width; 00110 _address_size = address_size; 00111 _alt_width = alt_width; 00112 _alt_size = alt_size; 00113 _data_width = data_width; 00114 _num_dummy_cycles = dummy_cycles; 00115 unlock(); 00116 00117 return QSPI_STATUS_OK; 00118 } 00119 00120 qspi_status_t QSPI::set_frequency(int hz) 00121 { 00122 qspi_status_t ret_status = QSPI_STATUS_OK; 00123 00124 if (_initialized) { 00125 lock(); 00126 _hz = hz; 00127 //If the same owner, just change freq. 00128 //Otherwise we may have to change mode as well, so call _acquire 00129 if (_owner == this) { 00130 if (QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) { 00131 ret_status = QSPI_STATUS_ERROR; 00132 } 00133 } else { 00134 _acquire(); 00135 } 00136 unlock(); 00137 } else { 00138 ret_status = QSPI_STATUS_ERROR; 00139 } 00140 00141 return ret_status; 00142 } 00143 00144 qspi_status_t QSPI::read(int address, char *rx_buffer, size_t *rx_length) 00145 { 00146 qspi_status_t ret_status = QSPI_STATUS_ERROR; 00147 00148 if (_initialized) { 00149 if ((rx_length != NULL) && (rx_buffer != NULL)) { 00150 if (*rx_length != 0) { 00151 lock(); 00152 if (true == _acquire()) { 00153 _build_qspi_command(QSPI_NO_INST, address, -1); 00154 if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) { 00155 ret_status = QSPI_STATUS_OK; 00156 } 00157 } 00158 unlock(); 00159 } 00160 } else { 00161 ret_status = QSPI_STATUS_INVALID_PARAMETER; 00162 } 00163 } 00164 00165 return ret_status; 00166 } 00167 00168 qspi_status_t QSPI::write(int address, const char *tx_buffer, size_t *tx_length) 00169 { 00170 qspi_status_t ret_status = QSPI_STATUS_ERROR; 00171 00172 if (_initialized) { 00173 if ((tx_length != NULL) && (tx_buffer != NULL)) { 00174 if (*tx_length != 0) { 00175 lock(); 00176 if (true == _acquire()) { 00177 _build_qspi_command(QSPI_NO_INST, address, -1); 00178 if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) { 00179 ret_status = QSPI_STATUS_OK; 00180 } 00181 } 00182 unlock(); 00183 } 00184 } else { 00185 ret_status = QSPI_STATUS_INVALID_PARAMETER; 00186 } 00187 } 00188 00189 return ret_status; 00190 } 00191 00192 qspi_status_t QSPI::read(qspi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length) 00193 { 00194 qspi_status_t ret_status = QSPI_STATUS_ERROR; 00195 00196 if (_initialized) { 00197 if ((rx_length != NULL) && (rx_buffer != NULL)) { 00198 if (*rx_length != 0) { 00199 lock(); 00200 if (true == _acquire()) { 00201 _build_qspi_command(instruction, address, alt); 00202 if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) { 00203 ret_status = QSPI_STATUS_OK; 00204 } 00205 } 00206 unlock(); 00207 } 00208 } else { 00209 ret_status = QSPI_STATUS_INVALID_PARAMETER; 00210 } 00211 } 00212 00213 return ret_status; 00214 } 00215 00216 qspi_status_t QSPI::write(qspi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length) 00217 { 00218 qspi_status_t ret_status = QSPI_STATUS_ERROR; 00219 00220 if (_initialized) { 00221 if ((tx_length != NULL) && (tx_buffer != NULL)) { 00222 if (*tx_length != 0) { 00223 lock(); 00224 if (true == _acquire()) { 00225 _build_qspi_command(instruction, address, alt); 00226 if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) { 00227 ret_status = QSPI_STATUS_OK; 00228 } 00229 } 00230 unlock(); 00231 } 00232 } else { 00233 ret_status = QSPI_STATUS_INVALID_PARAMETER; 00234 } 00235 } 00236 00237 return ret_status; 00238 } 00239 00240 qspi_status_t QSPI::command_transfer(qspi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) 00241 { 00242 qspi_status_t ret_status = QSPI_STATUS_ERROR; 00243 00244 if (_initialized) { 00245 lock(); 00246 if (true == _acquire()) { 00247 _build_qspi_command(instruction, address, -1); //We just need the command 00248 if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) { 00249 ret_status = QSPI_STATUS_OK; 00250 } 00251 } 00252 unlock(); 00253 } 00254 00255 return ret_status; 00256 } 00257 00258 void QSPI::lock() 00259 { 00260 _mutex->lock(); 00261 } 00262 00263 void QSPI::unlock() 00264 { 00265 _mutex->unlock(); 00266 } 00267 00268 // Note: Private helper function to initialize qspi HAL 00269 bool QSPI::_initialize() 00270 { 00271 if (_mode != 0 && _mode != 1) { 00272 _initialized = false; 00273 return _initialized; 00274 } 00275 00276 qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode); 00277 if (QSPI_STATUS_OK == ret) { 00278 _initialized = true; 00279 } else { 00280 _initialized = false; 00281 } 00282 00283 return _initialized; 00284 } 00285 00286 // Note: Private helper function to initialize qspi HAL 00287 bool QSPI::_initialize_direct() 00288 { 00289 if (_mode != 0 && _mode != 1) { 00290 _initialized = false; 00291 return _initialized; 00292 } 00293 00294 qspi_status_t ret = qspi_init_direct(&_qspi, _static_pinmap, _hz, _mode); 00295 if (QSPI_STATUS_OK == ret) { 00296 _initialized = true; 00297 } else { 00298 _initialized = false; 00299 } 00300 00301 return _initialized; 00302 } 00303 00304 // Note: Private function with no locking 00305 bool QSPI::_acquire() 00306 { 00307 if (_owner != this) { 00308 //This will set freq as well 00309 (this->*_init_func)(); 00310 _owner = this; 00311 } 00312 00313 return _initialized; 00314 } 00315 00316 void QSPI::_build_qspi_command(qspi_inst_t instruction, int address, int alt) 00317 { 00318 memset(&_qspi_command, 0, sizeof(qspi_command_t)); 00319 //Set up instruction phase parameters 00320 _qspi_command.instruction.bus_width = _inst_width; 00321 if (instruction != QSPI_NO_INST) { 00322 _qspi_command.instruction.value = instruction; 00323 _qspi_command.instruction.disabled = false; 00324 } else { 00325 _qspi_command.instruction.disabled = true; 00326 } 00327 00328 //Set up address phase parameters 00329 _qspi_command.address.bus_width = _address_width; 00330 _qspi_command.address.size = _address_size; 00331 if (address != -1) { 00332 _qspi_command.address.value = address; 00333 _qspi_command.address.disabled = false; 00334 } else { 00335 _qspi_command.address.disabled = true; 00336 } 00337 00338 //Set up alt phase parameters 00339 _qspi_command.alt.bus_width = _alt_width; 00340 _qspi_command.alt.size = _alt_size; 00341 if (alt != -1) { 00342 _qspi_command.alt.value = alt; 00343 _qspi_command.alt.disabled = false; 00344 } else { 00345 _qspi_command.alt.disabled = true; 00346 } 00347 00348 _qspi_command.dummy_count = _num_dummy_cycles; 00349 00350 //Set up bus width for data phase 00351 _qspi_command.data.bus_width = _data_width; 00352 } 00353 00354 } // namespace mbed 00355 00356 #endif
Generated on Tue Jul 12 2022 13:54:46 by
