takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qspi_test_utils.cpp Source File

qspi_test_utils.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018-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 "utest/utest.h"
00018 
00019 #include "hal/qspi_api.h"
00020 #include "qspi_test_utils.h"
00021 
00022 #include "unity/unity.h"
00023 
00024 #include <string.h> // for memset
00025 
00026 #include "flash_configs/flash_configs.h"
00027 #include "mbed.h"
00028 
00029 static qspi_status_t extended_enable(Qspi &qspi);
00030 static qspi_status_t extended_disable(Qspi &qspi);
00031 static qspi_status_t dual_enable(Qspi &qspi);
00032 static qspi_status_t dual_disable(Qspi &qspi);
00033 static qspi_status_t quad_enable(Qspi &qspi);
00034 static qspi_status_t quad_disable(Qspi &qspi);
00035 
00036 void QspiCommand::configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width,
00037                             qspi_bus_width_t data_width, qspi_bus_width_t alt_width,
00038                             qspi_address_size_t addr_size, qspi_alt_size_t alt_size,
00039                             int dummy_cycles)
00040 {
00041     memset(&_cmd, 0,  sizeof(qspi_command_t));
00042     _cmd.instruction.disabled = _cmd.address.disabled = _cmd.alt.disabled = true;
00043 
00044     _cmd.instruction.bus_width = inst_width;
00045     _cmd.address.bus_width = addr_width;
00046     _cmd.address.size = addr_size;
00047     _cmd.alt.bus_width = alt_width;
00048     _cmd.alt.size = alt_size;
00049     _cmd.data.bus_width = data_width;
00050     _cmd.dummy_count = dummy_cycles;
00051 }
00052 
00053 void QspiCommand::set_dummy_cycles(int dummy_cycles)
00054 {
00055     _cmd.dummy_count = dummy_cycles;
00056 }
00057 
00058 void QspiCommand::build(int instruction, int address, int alt)
00059 {
00060     _cmd.instruction.disabled = (instruction == QSPI_NONE);
00061     if (!_cmd.instruction.disabled) {
00062         _cmd.instruction.value = instruction;
00063     }
00064 
00065     _cmd.address.disabled = (address == QSPI_NONE);
00066     if (!_cmd.address.disabled) {
00067         _cmd.address.value = address;
00068     }
00069 
00070     _cmd.alt.disabled = (alt == QSPI_NONE);
00071     if (!_cmd.alt.disabled) {
00072         _cmd.alt.value = alt;
00073     }
00074 }
00075 
00076 qspi_command_t *QspiCommand::get()
00077 {
00078     return &_cmd;
00079 }
00080 
00081 
00082 qspi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q)
00083 {
00084     q.cmd.build(cmd);
00085     return qspi_command_transfer(&q.handle, q.cmd.get(), NULL, 0, buf, size);
00086 }
00087 
00088 qspi_status_t write_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q)
00089 {
00090     q.cmd.build(cmd);
00091     return qspi_command_transfer(&q.handle, q.cmd.get(), buf, size, NULL, 0);
00092 }
00093 
00094 
00095 QspiStatus flash_wait_for(uint32_t time_us, Qspi &qspi)
00096 {
00097     uint8_t reg[QSPI_STATUS_REG_SIZE];
00098     qspi_status_t ret;
00099     uint32_t curr_time;
00100 
00101     const ticker_data_t *const ticker = get_us_ticker_data();
00102     const uint32_t start = ticker_read(ticker);
00103 
00104     memset(reg, 255, QSPI_STATUS_REG_SIZE);
00105     do {
00106         ret = read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi);
00107         curr_time = ticker_read(ticker);
00108     } while (((reg[0] & STATUS_BIT_WIP) != 0) && ((curr_time - start) < time_us));
00109 
00110     if (((reg[0] & STATUS_BIT_WIP) == 0) && (ret == QSPI_STATUS_OK)) {
00111         return sOK;
00112     } else if (ret != QSPI_STATUS_OK) {
00113         return sError;
00114     } else if ((curr_time - start) >= time_us) {
00115         return sTimeout;
00116     }
00117     return sUnknown;
00118 }
00119 
00120 void flash_init(Qspi &qspi)
00121 {
00122     uint8_t status[QSPI_STATUS_REG_SIZE];
00123     qspi_status_t ret;
00124 
00125     qspi.cmd.build(QSPI_CMD_RDSR);
00126     ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, status, QSPI_STATUS_REG_SIZE);
00127     TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
00128 
00129     qspi.cmd.build(QSPI_CMD_RSTEN);
00130     ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
00131     TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
00132 
00133     WAIT_FOR(WRSR_MAX_TIME, qspi);
00134 
00135     qspi.cmd.build(QSPI_CMD_RST);
00136     ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
00137     TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
00138 
00139     WAIT_FOR(WAIT_MAX_TIME, qspi);
00140 }
00141 
00142 
00143 qspi_status_t write_enable(Qspi &qspi)
00144 {
00145     uint8_t reg[QSPI_STATUS_REG_SIZE];
00146     qspi.cmd.build(QSPI_CMD_WREN);
00147 
00148     if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) {
00149         return QSPI_STATUS_ERROR;
00150     }
00151     WAIT_FOR(WRSR_MAX_TIME, qspi);
00152 
00153     memset(reg, 0, QSPI_STATUS_REG_SIZE);
00154     if (read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) {
00155         return QSPI_STATUS_ERROR;
00156     }
00157 
00158     return ((reg[0] & STATUS_BIT_WEL) != 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR);
00159 }
00160 
00161 qspi_status_t write_disable(Qspi &qspi)
00162 {
00163     uint8_t reg[QSPI_STATUS_REG_SIZE];
00164     qspi.cmd.build(QSPI_CMD_WRDI);
00165 
00166     if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) {
00167         return QSPI_STATUS_ERROR;
00168     }
00169     WAIT_FOR(WRSR_MAX_TIME, qspi);
00170 
00171     memset(reg, 0, QSPI_STATUS_REG_SIZE);
00172     if (read_register(STATUS_REG, reg, QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) {
00173         return QSPI_STATUS_ERROR;
00174     }
00175 
00176     return ((reg[0] & STATUS_BIT_WEL) == 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR);
00177 }
00178 
00179 void log_register(uint32_t cmd, uint32_t reg_size, Qspi &qspi, const char *str)
00180 {
00181     qspi_status_t ret;
00182     static uint8_t reg[QSPI_MAX_REG_SIZE];
00183 
00184     ret = read_register(cmd, reg, reg_size, qspi);
00185     TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
00186 
00187     for (uint32_t j = 0; j < reg_size; j++) {
00188         utest_printf("%s byte %u (MSB first): ", str != NULL ? str : "", j);
00189         for (int i = 0; i < 8; i++) {
00190             utest_printf("%s ", ((reg[j] & (1 << (7 - i))) & 0xFF) == 0 ? "0" : "1");
00191         }
00192         utest_printf("\r\n");
00193     }
00194 }
00195 
00196 qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi)
00197 {
00198     qspi.cmd.build(erase_cmd, flash_addr);
00199     return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
00200 }
00201 
00202 qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
00203 {
00204     if(is_extended_mode(inst_width, addr_width, data_width)) {
00205         return extended_enable(qspi);
00206     } else if(is_dual_mode(inst_width, addr_width, data_width)) {
00207         return dual_enable(qspi);
00208     } else if(is_quad_mode(inst_width, addr_width, data_width)) {
00209         return quad_enable(qspi);
00210     } else {
00211         return QSPI_STATUS_OK;
00212     }
00213 }
00214 
00215 qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
00216 {
00217     if(is_extended_mode(inst_width, addr_width, data_width)) {
00218         return extended_disable(qspi);
00219     } else if(is_dual_mode(inst_width, addr_width, data_width)) {
00220         return dual_disable(qspi);
00221     } else if(is_quad_mode(inst_width, addr_width, data_width)) {
00222         return quad_disable(qspi);
00223     } else {
00224         return QSPI_STATUS_OK;
00225     }
00226 }
00227 
00228 static qspi_status_t extended_enable(Qspi &qspi)
00229 {
00230 #ifdef EXTENDED_SPI_ENABLE
00231     EXTENDED_SPI_ENABLE();
00232 #else
00233     return QSPI_STATUS_OK;
00234 #endif
00235 }
00236 
00237 static qspi_status_t extended_disable(Qspi &qspi)
00238 {
00239 #ifdef EXTENDED_SPI_DISABLE
00240     EXTENDED_SPI_DISABLE();
00241 #else
00242     return QSPI_STATUS_OK;
00243 #endif
00244 }
00245 
00246 static qspi_status_t dual_enable(Qspi &qspi)
00247 {
00248 #ifdef DUAL_ENABLE
00249     DUAL_ENABLE();
00250 #else
00251     return QSPI_STATUS_OK;
00252 #endif
00253 }
00254 
00255 static qspi_status_t dual_disable(Qspi &qspi)
00256 {
00257 #ifdef DUAL_DISABLE
00258     DUAL_DISABLE();
00259 #else
00260     return QSPI_STATUS_OK;
00261 #endif
00262 
00263 }
00264 
00265 static qspi_status_t quad_enable(Qspi &qspi)
00266 {
00267 #ifdef QUAD_ENABLE
00268     QUAD_ENABLE();
00269 #else
00270     return QSPI_STATUS_OK;
00271 #endif
00272 }
00273 
00274 static qspi_status_t quad_disable(Qspi &qspi)
00275 {
00276 #ifdef QUAD_DISABLE
00277     QUAD_DISABLE();
00278 #else
00279     return QSPI_STATUS_OK;
00280 #endif
00281 }
00282 
00283 qspi_status_t fast_mode_enable(Qspi &qspi)
00284 {
00285 #ifdef FAST_MODE_ENABLE
00286     FAST_MODE_ENABLE();
00287 #else
00288     return QSPI_STATUS_OK;
00289 #endif
00290 }
00291 
00292 qspi_status_t fast_mode_disable(Qspi &qspi)
00293 {
00294 #ifdef FAST_MODE_DISABLE
00295     FAST_MODE_DISABLE();
00296 #else
00297     return QSPI_STATUS_OK;
00298 #endif
00299 }
00300 
00301 bool is_extended_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
00302 {
00303     return (inst_width == QSPI_CFG_BUS_SINGLE) && ((addr_width != QSPI_CFG_BUS_SINGLE) || (data_width != QSPI_CFG_BUS_SINGLE));
00304 }
00305 
00306 bool is_dual_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
00307 {
00308     return (inst_width == QSPI_CFG_BUS_DUAL) && (addr_width == QSPI_CFG_BUS_DUAL) && (data_width == QSPI_CFG_BUS_DUAL);
00309 }
00310 
00311 bool is_quad_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
00312 {
00313     return (inst_width == QSPI_CFG_BUS_QUAD) && (addr_width == QSPI_CFG_BUS_QUAD) && (data_width == QSPI_CFG_BUS_QUAD);
00314 }