mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers QSPI.cpp Source File

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 QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, int mode) : _qspi()
00030 {
00031     _qspi_io0 = io0;
00032     _qspi_io1 = io1;
00033     _qspi_io2 = io2;
00034     _qspi_io3 = io3;
00035     _qspi_clk = sclk;
00036     _qspi_cs = ssel;
00037     _inst_width = QSPI_CFG_BUS_SINGLE;
00038     _address_width = QSPI_CFG_BUS_SINGLE;
00039     _address_size = QSPI_CFG_ADDR_SIZE_24;
00040     _alt_width = QSPI_CFG_BUS_SINGLE;
00041     _alt_size = QSPI_CFG_ALT_SIZE_8;
00042     _data_width = QSPI_CFG_BUS_SINGLE;
00043     _num_dummy_cycles = 0;
00044     _mode = mode;
00045     _hz = ONE_MHZ;
00046     _initialized = false;
00047 
00048     //Go ahead init the device here with the default config
00049     bool success = _initialize();
00050     MBED_ASSERT(success);
00051 }
00052 
00053 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)
00054 {
00055     qspi_status_t ret_status = QSPI_STATUS_OK;
00056 
00057     lock();
00058     _inst_width = inst_width;
00059     _address_width = address_width;
00060     _address_size = address_size;
00061     _alt_width = alt_width;
00062     _alt_size = alt_size;
00063     _data_width = data_width;
00064     _num_dummy_cycles = dummy_cycles;
00065 
00066     unlock();
00067 
00068     return ret_status;
00069 }
00070 
00071 qspi_status_t QSPI::set_frequency(int hz)
00072 {
00073     qspi_status_t ret_status = QSPI_STATUS_OK;
00074 
00075     if (_initialized) {
00076         lock();
00077         _hz = hz;
00078         //If the same owner, just change freq.
00079         //Otherwise we may have to change mode as well, so call _acquire
00080         if (_owner == this) {
00081             if (QSPI_STATUS_OK != qspi_frequency(&_qspi, _hz)) {
00082                 ret_status = QSPI_STATUS_ERROR;
00083             }
00084         } else {
00085             _acquire();
00086         }
00087         unlock();
00088     } else {
00089         ret_status = QSPI_STATUS_ERROR;
00090     }
00091 
00092     return ret_status;
00093 }
00094 
00095 qspi_status_t QSPI::read(int address, char *rx_buffer, size_t *rx_length)
00096 {
00097     qspi_status_t ret_status = QSPI_STATUS_ERROR;
00098 
00099     if (_initialized) {
00100         if ((rx_length != NULL) && (rx_buffer != NULL)) {
00101             if (*rx_length != 0) {
00102                 lock();
00103                 if (true == _acquire()) {
00104                     _build_qspi_command(-1, address, -1);
00105                     if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
00106                         ret_status = QSPI_STATUS_OK;
00107                     }
00108                 }
00109                 unlock();
00110             }
00111         } else {
00112             ret_status = QSPI_STATUS_INVALID_PARAMETER;
00113         }
00114     }
00115 
00116     return ret_status;
00117 }
00118 
00119 qspi_status_t QSPI::write(int address, const char *tx_buffer, size_t *tx_length)
00120 {
00121     qspi_status_t ret_status = QSPI_STATUS_ERROR;
00122 
00123     if (_initialized) {
00124         if ((tx_length != NULL) && (tx_buffer != NULL)) {
00125             if (*tx_length != 0) {
00126                 lock();
00127                 if (true == _acquire()) {
00128                     _build_qspi_command(-1, address, -1);
00129                     if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
00130                         ret_status = QSPI_STATUS_OK;
00131                     }
00132                 }
00133                 unlock();
00134             }
00135         } else {
00136             ret_status = QSPI_STATUS_INVALID_PARAMETER;
00137         }
00138     }
00139 
00140     return ret_status;
00141 }
00142 
00143 qspi_status_t QSPI::read(int instruction, int alt, int address, char *rx_buffer, size_t *rx_length)
00144 {
00145     qspi_status_t ret_status = QSPI_STATUS_ERROR;
00146 
00147     if (_initialized) {
00148         if ((rx_length != NULL) && (rx_buffer != NULL)) {
00149             if (*rx_length != 0) {
00150                 lock();
00151                 if (true == _acquire()) {
00152                     _build_qspi_command(instruction, address, alt);
00153                     if (QSPI_STATUS_OK == qspi_read(&_qspi, &_qspi_command, rx_buffer, rx_length)) {
00154                         ret_status = QSPI_STATUS_OK;
00155                     }
00156                 }
00157                 unlock();
00158             }
00159         } else {
00160             ret_status = QSPI_STATUS_INVALID_PARAMETER;
00161         }
00162     }
00163 
00164     return ret_status;
00165 }
00166 
00167 qspi_status_t QSPI::write(int instruction, int alt, int address, const char *tx_buffer, size_t *tx_length)
00168 {
00169     qspi_status_t ret_status = QSPI_STATUS_ERROR;
00170 
00171     if (_initialized) {
00172         if ((tx_length != NULL) && (tx_buffer != NULL)) {
00173             if (*tx_length != 0) {
00174                 lock();
00175                 if (true == _acquire()) {
00176                     _build_qspi_command(instruction, address, alt);
00177                     if (QSPI_STATUS_OK == qspi_write(&_qspi, &_qspi_command, tx_buffer, tx_length)) {
00178                         ret_status = QSPI_STATUS_OK;
00179                     }
00180                 }
00181                 unlock();
00182             }
00183         } else {
00184             ret_status = QSPI_STATUS_INVALID_PARAMETER;
00185         }
00186     }
00187 
00188     return ret_status;
00189 }
00190 
00191 qspi_status_t QSPI::command_transfer(int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
00192 {
00193     qspi_status_t ret_status = QSPI_STATUS_ERROR;
00194 
00195     if (_initialized) {
00196         lock();
00197         if (true == _acquire()) {
00198             _build_qspi_command(instruction, address, -1); //We just need the command
00199             if (QSPI_STATUS_OK == qspi_command_transfer(&_qspi, &_qspi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
00200                 ret_status = QSPI_STATUS_OK;
00201             }
00202         }
00203         unlock();
00204     }
00205 
00206     return ret_status;
00207 }
00208 
00209 void QSPI::lock()
00210 {
00211     _mutex->lock();
00212 }
00213 
00214 void QSPI::unlock()
00215 {
00216     _mutex->unlock();
00217 }
00218 
00219 // Note: Private helper function to initialize qspi HAL
00220 bool QSPI::_initialize()
00221 {
00222     if (_mode != 0 && _mode != 1) {
00223         _initialized = false;
00224         return _initialized;
00225     }
00226 
00227     qspi_status_t ret = qspi_init(&_qspi, _qspi_io0, _qspi_io1, _qspi_io2, _qspi_io3, _qspi_clk, _qspi_cs, _hz, _mode);
00228     if (QSPI_STATUS_OK == ret) {
00229         _initialized = true;
00230     } else {
00231         _initialized = false;
00232     }
00233 
00234     return _initialized;
00235 }
00236 
00237 // Note: Private function with no locking
00238 bool QSPI::_acquire()
00239 {
00240     if (_owner != this) {
00241         //This will set freq as well
00242         _initialize();
00243         _owner = this;
00244     }
00245 
00246     return _initialized;
00247 }
00248 
00249 void QSPI::_build_qspi_command(int instruction, int address, int alt)
00250 {
00251     memset(&_qspi_command, 0,  sizeof(qspi_command_t));
00252     //Set up instruction phase parameters
00253     _qspi_command.instruction.bus_width = _inst_width;
00254     if (instruction != -1) {
00255         _qspi_command.instruction.value = instruction;
00256         _qspi_command.instruction.disabled = false;
00257     } else {
00258         _qspi_command.instruction.disabled = true;
00259     }
00260 
00261     //Set up address phase parameters
00262     _qspi_command.address.bus_width = _address_width;
00263     _qspi_command.address.size = _address_size;
00264     if (address != -1) {
00265         _qspi_command.address.value = address;
00266         _qspi_command.address.disabled = false;
00267     } else {
00268         _qspi_command.address.disabled = true;
00269     }
00270 
00271     //Set up alt phase parameters
00272     _qspi_command.alt.bus_width = _alt_width;
00273     _qspi_command.alt.size = _alt_size;
00274     if (alt != -1) {
00275         _qspi_command.alt.value = alt;
00276         _qspi_command.alt.disabled = false;
00277     } else {
00278         _qspi_command.alt.disabled = true;
00279     }
00280 
00281     _qspi_command.dummy_count = _num_dummy_cycles;
00282 
00283     //Set up bus width for data phase
00284     _qspi_command.data.bus_width = _data_width;
00285 }
00286 
00287 } // namespace mbed
00288 
00289 #endif