takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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