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
MbedTester.cpp
00001 /* 00002 * Copyright (c) 2019, Arm Limited and affiliates. 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 "MbedTester.h" 00019 #include "fpga_config.h" 00020 #include "BlockDevice.h" 00021 #include "rtos/ThisThread.h" 00022 #include "platform/mbed_wait_api.h" 00023 #include "platform/mbed_error.h" 00024 #include "drivers/MbedCRC.h" 00025 00026 #define mbed_tester_printf(...) 00027 00028 #define PHYSICAL_PINS 128 00029 #define LOGICAL_PINS 8 00030 #define FIRMWARE_SIZE 2192012 00031 #define FIRMWARE_REGION_SIZE 0x220000 00032 #define FIRMWARE_HEADER_SIZE 0x10000 00033 #define FLASH_SECTOR_SIZE 0x1000 00034 #define LENGTH_SIZE 0x4 00035 #define CRC_SIZE 0x4 00036 #define FLASH_SPI_FREQ_HZ 2000000 00037 #define ANALOG_COUNT 4 00038 00039 #define PHYSICAL_NC ((MbedTester::PhysicalIndex)0xFF) 00040 00041 static const uint8_t KEY[8] = { 00042 0x92, 0x9d, 0x9a, 0x9b, 00043 0x29, 0x35, 0xa2, 0x65 00044 }; 00045 00046 template<size_t width> 00047 class MbedTesterBitMap { 00048 public: 00049 00050 MbedTesterBitMap() 00051 { 00052 for (size_t i = 0; i < _count; i++) { 00053 _bitmap[i] = 0; 00054 } 00055 } 00056 00057 bool get(size_t index) 00058 { 00059 if (index >= width) { 00060 return false; 00061 } 00062 return _bitmap[index / 32] & (1 << (index % 32)) ? true : false; 00063 } 00064 00065 void set(size_t index) 00066 { 00067 if (index >= width) { 00068 return; 00069 } 00070 _bitmap[index / 32] |= 1 << (index % 32); 00071 } 00072 00073 void clear(size_t index) 00074 { 00075 if (index >= width) { 00076 return; 00077 } 00078 _bitmap[index / 32] &= ~(1 << (index % 32)); 00079 } 00080 00081 private: 00082 00083 static const size_t _count = (width + 31) / 32; 00084 uint32_t _bitmap[(width + 31) / 32]; 00085 }; 00086 00087 static uint8_t spi_transfer(mbed::DigitalInOut *clk, mbed::DigitalInOut *mosi, mbed::DigitalInOut *miso, uint8_t data) 00088 { 00089 uint8_t ret = 0; 00090 for (int i = 0; i < 8; i++) { 00091 *clk = 0; 00092 *mosi = (data >> (7 - i)) & 1; 00093 wait_ns(100); 00094 *clk = 1; 00095 ret |= *miso ? 1 << (7 - i) : 0; 00096 wait_ns(100); 00097 } 00098 return ret; 00099 } 00100 00101 static void mbed_tester_command(mbed::DigitalInOut *clk, mbed::DigitalInOut *mosi, mbed::DigitalInOut *miso, uint8_t miso_index, uint32_t addr, bool write_n_read, uint8_t *data, uint8_t size) 00102 { 00103 // 8 - Start Key 00104 for (uint32_t i = 0; i < sizeof(KEY); i++) { 00105 spi_transfer(clk, mosi, miso, KEY[i]); 00106 } 00107 00108 // 1 - Physical pin index for MISO 00109 spi_transfer(clk, mosi, miso, miso_index); 00110 00111 // 1 - Number of SPI transfers which follow (= N + 5) 00112 spi_transfer(clk, mosi, miso, size + 5); 00113 00114 // 4 - Little endian address for transfer 00115 spi_transfer(clk, mosi, miso, (addr >> (8 * 0)) & 0xFF); 00116 spi_transfer(clk, mosi, miso, (addr >> (8 * 1)) & 0xFF); 00117 spi_transfer(clk, mosi, miso, (addr >> (8 * 2)) & 0xFF); 00118 spi_transfer(clk, mosi, miso, (addr >> (8 * 3)) & 0xFF); 00119 00120 // 1 - direction 00121 spi_transfer(clk, mosi, miso, write_n_read ? 1 : 0); 00122 00123 // N - Data to read or write 00124 if (write_n_read) {//read: false, write: true 00125 for (int i = 0; i < size; i++) { 00126 spi_transfer(clk, mosi, miso, data[i]); 00127 } 00128 } else { 00129 for (int i = 0; i < size; i++) { 00130 data[i] = spi_transfer(clk, mosi, miso, 0); 00131 } 00132 } 00133 *clk = 0; 00134 00135 } 00136 00137 static bool mbed_tester_test(mbed::DigitalInOut *clk, mbed::DigitalInOut *mosi, mbed::DigitalInOut *miso, uint8_t miso_index) 00138 { 00139 uint8_t buf[4]; 00140 memset(buf, 0, sizeof(buf)); 00141 mbed_tester_command(clk, mosi, miso, miso_index, TESTER_CONTROL, false, buf, sizeof(buf)); 00142 return memcmp(buf, "mbed", sizeof(buf)) == 0; 00143 } 00144 00145 00146 class MbedTesterBlockDevice : public BlockDevice { 00147 public: 00148 00149 MbedTesterBlockDevice(mbed::DigitalInOut &mosi, mbed::DigitalInOut &miso, mbed::DigitalInOut &clk, mbed::DigitalInOut &cs, uint32_t frequency) 00150 : _mosi(mosi), _miso(miso), _clk(clk), _cs(cs), _wait_ns(1000000000 / frequency / 2), _init(false) 00151 { 00152 00153 // Set initial values 00154 _cs.write(1); 00155 _clk.write(0); 00156 00157 // Set direction 00158 _mosi.output(); 00159 _miso.input(); 00160 _clk.output(); 00161 _cs.output(); 00162 } 00163 00164 00165 virtual int init() 00166 { 00167 if (_check_id()) { 00168 _init = true; 00169 } 00170 return _init ? BD_ERROR_OK : BD_ERROR_DEVICE_ERROR; 00171 } 00172 00173 virtual int deinit() 00174 { 00175 _init = false; 00176 return BD_ERROR_OK; 00177 } 00178 00179 virtual int read(void *buffer, bd_addr_t addr, bd_size_t size) 00180 { 00181 if (!is_valid_read(addr, size) || !_init) { 00182 return BD_ERROR_DEVICE_ERROR; 00183 } 00184 00185 _assert_cs(true); 00186 00187 uint8_t cmd[] = { 00188 0x0B, // Fast read 00189 (uint8_t)(addr >> (2 * 8)), // Address 00190 (uint8_t)(addr >> (1 * 8)), 00191 (uint8_t)(addr >> (0 * 8)), 00192 0x00 // Dummy 00193 }; 00194 _write((char *)cmd, sizeof(cmd), NULL, 0); 00195 _write(NULL, 0, (char *)buffer, size); 00196 00197 _assert_cs(false); 00198 00199 return BD_ERROR_OK; 00200 } 00201 00202 virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size) 00203 { 00204 if (!is_valid_program(addr, size) || !_init) { 00205 return BD_ERROR_DEVICE_ERROR; 00206 } 00207 00208 const bd_size_t max_program_size = 256; 00209 bd_size_t programmed = 0; 00210 while (programmed < size) { 00211 const bd_size_t size_left = size - programmed; 00212 const bd_size_t program_size = size_left < max_program_size ? size_left : max_program_size; 00213 00214 _write_enable(); 00215 _page_program(addr + programmed, (const uint8_t *)buffer, program_size); 00216 _wait_ready(); 00217 programmed += program_size; 00218 } 00219 00220 return BD_ERROR_OK; 00221 } 00222 00223 virtual int erase(bd_addr_t addr, bd_size_t size) 00224 { 00225 if (!is_valid_erase(addr, size) || !_init) { 00226 return BD_ERROR_DEVICE_ERROR; 00227 } 00228 00229 if ((addr == 0) && (size == FLASH_SECTOR_SIZE)) { 00230 // Allow 4K erase only on the first sector. The flash on the basys3 does 00231 // not allow sector erases at the higher addresses. 00232 _write_enable(); 00233 _sector_erase(addr); 00234 _wait_ready(); 00235 return BD_ERROR_OK; 00236 } 00237 00238 if (!is_valid_erase(addr, size)) { 00239 return BD_ERROR_DEVICE_ERROR; 00240 } 00241 00242 const uint32_t erase_size = get_erase_size(); 00243 bd_size_t erased = 0; 00244 while (erased < erase_size) { 00245 _write_enable(); 00246 _block_erase(addr + erased); 00247 _wait_ready(); 00248 erased += erase_size; 00249 } 00250 return BD_ERROR_OK; 00251 } 00252 00253 virtual bd_size_t get_read_size() const 00254 { 00255 return 1; 00256 } 00257 00258 virtual bd_size_t get_program_size() const 00259 { 00260 return 1; 00261 } 00262 00263 virtual bd_size_t get_erase_size() const 00264 { 00265 return 0x10000; 00266 } 00267 00268 virtual bd_size_t get_erase_size(bd_addr_t addr) const 00269 { 00270 return get_erase_size(); 00271 } 00272 00273 virtual bd_size_t size() const 00274 { 00275 return 8 * 1024 * 1024; 00276 } 00277 00278 virtual const char *get_type() const 00279 { 00280 return "MbedTesterBlockDevice"; 00281 } 00282 00283 protected: 00284 00285 void _write_enable() 00286 { 00287 uint8_t command[1]; 00288 00289 _assert_cs(true); 00290 00291 command[0] = 0x06; 00292 _write((char *)command, 1, NULL, 0); 00293 00294 _assert_cs(false); 00295 } 00296 00297 void _sector_erase(uint32_t addr) 00298 { 00299 uint8_t command[4]; 00300 00301 _assert_cs(true); 00302 00303 command[0] = 0x20; 00304 command[1] = (addr >> (2 * 8)) & 0xFF; 00305 command[2] = (addr >> (1 * 8)) & 0xFF; 00306 command[3] = (addr >> (0 * 8)) & 0xFF; 00307 _write((char *)command, 4, NULL, 0); 00308 00309 _assert_cs(false); 00310 } 00311 00312 void _block_erase(uint32_t addr) 00313 { 00314 uint8_t command[4]; 00315 00316 _assert_cs(true); 00317 00318 command[0] = 0xD8; 00319 command[1] = (addr >> (2 * 8)) & 0xFF; 00320 command[2] = (addr >> (1 * 8)) & 0xFF; 00321 command[3] = (addr >> (0 * 8)) & 0xFF; 00322 _write((char *)command, 4, NULL, 0); 00323 00324 _assert_cs(false); 00325 } 00326 00327 void _page_program(uint32_t addr, const uint8_t *data, uint32_t size) 00328 { 00329 uint8_t command[4]; 00330 00331 _assert_cs(true); 00332 00333 command[0] = 0x02; 00334 command[1] = (addr >> (2 * 8)) & 0xFF; 00335 command[2] = (addr >> (1 * 8)) & 0xFF; 00336 command[3] = (addr >> (0 * 8)) & 0xFF; 00337 _write((char *)command, 4, NULL, 0); 00338 _write((char *)data, size, NULL, 0); 00339 00340 _assert_cs(false); 00341 } 00342 00343 void _wait_ready() 00344 { 00345 uint8_t command[2]; 00346 uint8_t response[2]; 00347 00348 // Wait for ready 00349 response[1] = 0xFF; 00350 do { 00351 _assert_cs(true); 00352 00353 command[0] = 0x05; 00354 command[1] = 0; 00355 _write((char *)command, 2, (char *)response, 2); 00356 00357 _assert_cs(false); 00358 00359 } while (response[1] & (1 << 0)); 00360 } 00361 00362 bool _check_id() 00363 { 00364 uint8_t command[1]; 00365 char id0[3]; 00366 char id1[3]; 00367 00368 // Read ID twice and verify it is the same 00369 00370 _assert_cs(true); 00371 00372 command[0] = 0x9F; 00373 _write((char *)command, 1, NULL, 0); 00374 _write(NULL, 0, id0, sizeof(id0)); 00375 00376 _assert_cs(false); 00377 00378 _assert_cs(true); 00379 00380 command[0] = 0x9F; 00381 _write((char *)command, 1, NULL, 0); 00382 _write(NULL, 0, id1, sizeof(id1)); 00383 00384 _assert_cs(false); 00385 00386 // Return failure if IDs are not the same 00387 for (size_t i = 0; i < sizeof(id0); i++) { 00388 if (id0[i] != id1[i]) { 00389 return false; 00390 } 00391 } 00392 00393 // If all 0xFF return failure 00394 if ((id0[0] == 0xFF) && (id0[1] == 0xFF) && (id0[2] == 0xFF)) { 00395 return false; 00396 } 00397 00398 // If all 0x00 return failure 00399 if ((id0[0] == 0x00) && (id0[1] == 0x00) && (id0[2] == 0x00)) { 00400 return false; 00401 } 00402 00403 return true; 00404 } 00405 00406 void _write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) 00407 { 00408 int transfers = 0; 00409 if (tx_length > transfers) { 00410 transfers = tx_length; 00411 } 00412 if (rx_length > transfers) { 00413 transfers = rx_length; 00414 } 00415 00416 for (int i = 0; i < transfers; i++) { 00417 uint8_t out = i < tx_length ? tx_buffer[i] : 0; 00418 uint8_t in = 0; 00419 for (int j = 0; j < 8; j++) { 00420 _mosi.write((out >> 7) & 1); 00421 out = out << 1; 00422 wait_ns(_wait_ns); 00423 00424 _clk.write(1); 00425 in = (in << 1) | (_miso.read() ? 1 : 0); 00426 wait_ns(_wait_ns); 00427 00428 _clk.write(0); 00429 } 00430 if (i < rx_length) { 00431 rx_buffer[i] = in; 00432 } 00433 } 00434 } 00435 00436 void _assert_cs(bool asserted) 00437 { 00438 _clk = 0; 00439 wait_ns(_wait_ns); 00440 _cs = asserted ? 0 : 1; 00441 wait_ns(_wait_ns); 00442 } 00443 00444 mbed::DigitalInOut &_mosi; 00445 mbed::DigitalInOut &_miso; 00446 mbed::DigitalInOut &_clk; 00447 mbed::DigitalInOut &_cs; 00448 uint32_t _wait_ns; 00449 bool _init; 00450 }; 00451 00452 static void dummy_progress(uint8_t) 00453 { 00454 // Stub progress handler for firmware update/dump 00455 } 00456 00457 // Header taken from app note XAPP1081. Information on the commands 00458 // can be found in the 7 Series FPGA configuration user guide - UG470 00459 static const uint8_t BANK_B_SELECT[] = { 00460 0x20, 0x00, 0x00, 0x00, // 0x20000000 NOP 00461 0x30, 0x02, 0x00, 0x01, // 0x30020001 WRITE to WBSTAR (Warm boot start address register) 00462 0x00, 0x23, 0x00, 0x00, // 0x00230000 0x230000 = Second bank start address 00463 0x30, 0x00, 0x80, 0x01, // 0x30008001 WRITE to CMD register 00464 0x00, 0x00, 0x00, 0x0F, // 0x0000000F 0x0F = IPROG command (starts warm boot) 00465 0x20, 0x00, 0x00, 0x00, // 0x20000000 NOP 00466 0x20, 0x00, 0x00, 0x00, // 0x20000000 NOP 00467 0x20, 0x00, 0x00, 0x00 // 0x20000000 NOP 00468 }; 00469 00470 static const uint8_t SYNC_WORD[] = { 00471 0xAA, 0x99, 0x55, 0x66 // 0xAA995566 Sync word 00472 }; 00473 00474 static bool _firmware_header_valid(BlockDevice &flash, bool &valid) 00475 { 00476 uint8_t buf[64]; 00477 size_t pos = 0; 00478 size_t read_size; 00479 00480 // Default to invalid 00481 valid = false; 00482 00483 // Check that first portion is erased 00484 while (pos < FLASH_SECTOR_SIZE - sizeof(SYNC_WORD)) { 00485 read_size = FLASH_SECTOR_SIZE - pos; 00486 if (read_size > sizeof(buf)) { 00487 read_size = sizeof(buf); 00488 } 00489 if (flash.read(buf, pos, read_size) != BD_ERROR_OK) { 00490 return false; 00491 } 00492 pos += read_size; 00493 for (size_t i = 0; i < read_size; i++) { 00494 if (buf[i] != 0xFF) { 00495 valid = false; 00496 return true; 00497 } 00498 } 00499 } 00500 00501 // Skip the sync word 00502 pos += sizeof(SYNC_WORD); 00503 00504 // Check that BANK_B_SELECT is valid 00505 read_size = sizeof(BANK_B_SELECT); 00506 if (flash.read(buf, pos, read_size) != BD_ERROR_OK) { 00507 return false; 00508 } 00509 pos += read_size; 00510 if (memcmp(buf, BANK_B_SELECT, sizeof(BANK_B_SELECT)) != 0) { 00511 valid = false; 00512 return true; 00513 } 00514 00515 // Check if the rest is 0xFF 00516 while (pos < FIRMWARE_HEADER_SIZE) { 00517 read_size = FIRMWARE_HEADER_SIZE - pos; 00518 if (read_size > sizeof(buf)) { 00519 read_size = sizeof(buf); 00520 } 00521 if (flash.read(buf, pos, read_size) != BD_ERROR_OK) { 00522 return false; 00523 } 00524 pos += read_size; 00525 for (size_t i = 0; i < read_size; i++) { 00526 if (buf[i] != 0xFF) { 00527 valid = false; 00528 return true; 00529 } 00530 } 00531 } 00532 00533 valid = true; 00534 return true; 00535 } 00536 00537 static bool _firmware_get_active_bank(BlockDevice &flash, bool &second_bank_active) 00538 { 00539 uint8_t buf[sizeof(SYNC_WORD)]; 00540 00541 if (flash.read(buf, FLASH_SECTOR_SIZE - sizeof(SYNC_WORD), sizeof(SYNC_WORD)) != BD_ERROR_OK) { 00542 return false; 00543 } 00544 00545 second_bank_active = memcmp(buf, SYNC_WORD, sizeof(SYNC_WORD)) == 0 ? true : false; 00546 return true; 00547 } 00548 00549 static bool _firmware_set_active_bank(BlockDevice &flash, bool second_bank) 00550 { 00551 bool valid = false; 00552 if (!_firmware_header_valid(flash, valid)) { 00553 return false; 00554 } 00555 if (!valid) { 00556 if (flash.erase(0, FIRMWARE_HEADER_SIZE) != BD_ERROR_OK) { 00557 return false; 00558 } 00559 if (flash.program(BANK_B_SELECT, FLASH_SECTOR_SIZE, sizeof(BANK_B_SELECT)) != BD_ERROR_OK) { 00560 return false; 00561 } 00562 } 00563 if (!flash.erase(0, FLASH_SECTOR_SIZE)) { 00564 return false; 00565 } 00566 00567 00568 if (second_bank) { 00569 // Write the sync word. Before the sync word is written the FPGA will boot from the first bank. 00570 // After the sync word is written the FPGA will boot from the second bank. 00571 if (flash.program(SYNC_WORD, FLASH_SECTOR_SIZE - sizeof(SYNC_WORD), sizeof(SYNC_WORD)) != BD_ERROR_OK) { 00572 return false; 00573 } 00574 } 00575 00576 return true; 00577 } 00578 00579 MbedTester::MbedTester(const PinList *form_factor, const PinList *exclude_pins) 00580 : _form_factor(form_factor), _exclude_pins(exclude_pins), _control_auto(true), _control_valid(false), 00581 _clk_index(PHYSICAL_NC), _mosi_index(PHYSICAL_NC), _miso_index(PHYSICAL_NC), _aux_index(PHYSICAL_NC), 00582 _clk(NULL), _mosi(NULL), _miso(NULL), _aux(NULL) 00583 { 00584 _reset(); 00585 _init_io_exp_rst_flag = 0; 00586 } 00587 00588 MbedTester::~MbedTester() 00589 { 00590 _free_control_pins(); 00591 } 00592 00593 00594 void MbedTester::set_control_pins_auto() 00595 { 00596 _control_auto = true; 00597 } 00598 00599 void MbedTester::set_control_pins_manual(PinName clk, PinName mosi, PinName miso, PinName aux) 00600 { 00601 int index; 00602 index = _form_factor.index(clk); 00603 if (index < 0) { 00604 error("Invalid CLK index"); 00605 } 00606 PhysicalIndex clk_index = index; 00607 00608 index = _form_factor.index(mosi); 00609 if (index < 0) { 00610 error("Invalid MOSI index"); 00611 } 00612 PhysicalIndex mosi_index = index; 00613 00614 index = _form_factor.index(miso); 00615 if (index < 0) { 00616 error("Invalid MISO index"); 00617 } 00618 PhysicalIndex miso_index = index; 00619 00620 index = _form_factor.index(aux); 00621 if (index < 0) { 00622 error("Invalid AUX index"); 00623 } 00624 PhysicalIndex aux_index = index; 00625 00626 if (clk_index + 1 != mosi_index) { 00627 error("MOSI pin index does not follow CLK as required"); 00628 } 00629 00630 if ((miso_index == clk_index) || (miso_index == mosi_index)) { 00631 error("MISO conflicts with a control channel"); 00632 } 00633 if ((aux_index == clk_index) || (aux_index == mosi_index) || (aux_index == miso_index)) { 00634 error("AUX conflicts with a control channel"); 00635 } 00636 00637 // All criteria have been met so set the pins 00638 _control_auto = false; 00639 _free_control_pins(); 00640 _clk_index = clk_index; 00641 _mosi_index = mosi_index; 00642 _miso_index = miso_index; 00643 _aux_index = aux_index; 00644 _setup_control_pins(); 00645 _control_valid = true; 00646 } 00647 00648 bool MbedTester::firmware_dump(mbed::FileHandle *dest, mbed::Callback<void(uint8_t)> progress) 00649 { 00650 _update_control_pins(); 00651 00652 if (!progress) { 00653 progress = mbed::callback(dummy_progress); 00654 } 00655 00656 // Mapping intentionally different from control channel to prevent 00657 // unintentional activation (clk and mosi flipped) 00658 MbedTesterBlockDevice flash(*_clk, *_miso, *_mosi, *_aux, FLASH_SPI_FREQ_HZ); 00659 sys_pin_mode_spi_serial_flash(_clk_index, _miso_index, _mosi_index, _aux_index); 00660 00661 progress(0); 00662 00663 if (flash.init() != BD_ERROR_OK) { 00664 sys_pin_mode_disabled(); 00665 return false; 00666 } 00667 00668 // Set the start of dump to the active bank 00669 bool second_bank_active; 00670 if (!_firmware_get_active_bank(flash, second_bank_active)) { 00671 // Error determining active bank 00672 sys_pin_mode_disabled(); 00673 return false; 00674 } 00675 const uint32_t start = FIRMWARE_HEADER_SIZE + (second_bank_active ? FIRMWARE_REGION_SIZE : 0); 00676 00677 // Get the firmware size 00678 uint32_t offset = 0; 00679 uint8_t buf[256]; 00680 uint32_t prev_percent_done = 0; 00681 if (flash.read(buf, start + offset, LENGTH_SIZE) != BD_ERROR_OK) { 00682 sys_pin_mode_disabled(); 00683 return false; 00684 } 00685 if (dest->write(buf, LENGTH_SIZE) != LENGTH_SIZE) { 00686 sys_pin_mode_disabled(); 00687 return false; 00688 } 00689 offset += LENGTH_SIZE; 00690 uint32_t data_size = (buf[0] << (0 * 8)) | 00691 (buf[1] << (1 * 8)) | 00692 (buf[2] << (2 * 8)) | 00693 (buf[3] << (3 * 8)); 00694 if (data_size > FIRMWARE_REGION_SIZE - LENGTH_SIZE - CRC_SIZE) { 00695 data_size = FIRMWARE_REGION_SIZE - LENGTH_SIZE - CRC_SIZE; 00696 } 00697 const uint32_t firmware_size = data_size + LENGTH_SIZE + CRC_SIZE; 00698 00699 // Dump firmware 00700 while (offset < firmware_size) { 00701 uint32_t read_size = firmware_size - offset; 00702 if (read_size > sizeof(buf)) { 00703 read_size = sizeof(buf); 00704 } 00705 if (flash.read(buf, start + offset, read_size) != BD_ERROR_OK) { 00706 sys_pin_mode_disabled(); 00707 return false; 00708 } 00709 ssize_t write_size = dest->write(buf, read_size); 00710 if ((uint32_t)write_size != read_size) { 00711 sys_pin_mode_disabled(); 00712 return false; 00713 } 00714 offset += read_size; 00715 00716 const uint8_t percent_done = (offset * 100) / firmware_size; 00717 if (percent_done != prev_percent_done) { 00718 progress(percent_done); 00719 prev_percent_done = percent_done; 00720 } 00721 } 00722 00723 progress(100); 00724 00725 sys_pin_mode_disabled(); 00726 return true; 00727 } 00728 00729 bool MbedTester::firmware_dump_all(mbed::FileHandle *dest, mbed::Callback<void(uint8_t)> progress) 00730 { 00731 _update_control_pins(); 00732 00733 if (!progress) { 00734 progress = mbed::callback(dummy_progress); 00735 } 00736 00737 // Mapping intentionally different from control channel to prevent 00738 // unintentional activation (clk and mosi flipped) 00739 MbedTesterBlockDevice flash(*_clk, *_miso, *_mosi, *_aux, FLASH_SPI_FREQ_HZ); 00740 sys_pin_mode_spi_serial_flash(_clk_index, _miso_index, _mosi_index, _aux_index); 00741 00742 progress(0); 00743 00744 if (flash.init() != BD_ERROR_OK) { 00745 sys_pin_mode_disabled(); 00746 return false; 00747 } 00748 00749 uint32_t pos = 0; 00750 uint8_t buf[256]; 00751 uint32_t prev_percent_done = 0; 00752 const uint32_t total_size = flash.size(); 00753 while (pos < total_size) { 00754 uint32_t read_size = total_size - pos; 00755 if (read_size > sizeof(buf)) { 00756 read_size = sizeof(buf); 00757 } 00758 if (flash.read(buf, pos, read_size) != BD_ERROR_OK) { 00759 sys_pin_mode_disabled(); 00760 return false; 00761 } 00762 ssize_t write_size = dest->write(buf, read_size); 00763 if ((uint32_t)write_size != read_size) { 00764 sys_pin_mode_disabled(); 00765 return false; 00766 } 00767 pos += read_size; 00768 00769 const uint8_t percent_done = (pos * 100) / total_size; 00770 if (percent_done != prev_percent_done) { 00771 progress(percent_done); 00772 prev_percent_done = percent_done; 00773 } 00774 } 00775 00776 progress(100); 00777 00778 sys_pin_mode_disabled(); 00779 return true; 00780 } 00781 00782 bool MbedTester::firmware_update(mbed::FileHandle *src, mbed::Callback<void(uint8_t)> progress) 00783 { 00784 _update_control_pins(); 00785 00786 if (!progress) { 00787 progress = mbed::callback(dummy_progress); 00788 } 00789 00790 // Mapping intentionally different from control channel to prevent 00791 // unintentional activation (clk and mosi flipped) 00792 MbedTesterBlockDevice flash(*_clk, *_miso, *_mosi, *_aux, FLASH_SPI_FREQ_HZ); 00793 sys_pin_mode_spi_serial_flash(_clk_index, _miso_index, _mosi_index, _aux_index); 00794 00795 progress(0); 00796 00797 if (flash.init() != BD_ERROR_OK) { 00798 sys_pin_mode_disabled(); 00799 return false; 00800 } 00801 00802 // Validate file size 00803 const uint32_t file_size = src->size(); 00804 if (file_size > FIRMWARE_REGION_SIZE) { 00805 // Firmware image too big 00806 sys_pin_mode_disabled(); 00807 return false; 00808 } 00809 if (file_size < LENGTH_SIZE + CRC_SIZE) { 00810 // Firmware image too small 00811 sys_pin_mode_disabled(); 00812 return false; 00813 } 00814 00815 // Set the start of programming to the inactive bank 00816 bool second_bank_active; 00817 if (!_firmware_get_active_bank(flash, second_bank_active)) { 00818 // Error determining active bank 00819 sys_pin_mode_disabled(); 00820 return false; 00821 } 00822 const uint32_t start = FIRMWARE_HEADER_SIZE + (second_bank_active ? 0 : FIRMWARE_REGION_SIZE); 00823 00824 // Setup CRC calculation 00825 uint32_t crc; 00826 mbed::MbedCRC<POLY_32BIT_ANSI, 32> ct; 00827 if (ct.compute_partial_start(&crc) != 0) { 00828 sys_pin_mode_disabled(); 00829 return false; 00830 } 00831 00832 uint8_t buf[256]; 00833 const bd_size_t erase_size = flash.get_erase_size(); 00834 uint32_t offset = 0; 00835 uint32_t prev_percent_done = 0; 00836 uint32_t stored_crc = 0; 00837 bool size_valid = false; 00838 while (offset < file_size) { 00839 00840 // Prepare data 00841 uint32_t program_size = file_size - offset; 00842 if (program_size > sizeof(buf)) { 00843 program_size = sizeof(buf); 00844 } 00845 ssize_t read_size = src->read(buf, program_size); 00846 if (read_size < 0) { 00847 sys_pin_mode_disabled(); 00848 return false; 00849 } else if (read_size == 0) { 00850 break; 00851 } 00852 program_size = read_size; 00853 00854 // Record values and calculate checksum 00855 uint32_t crc_offset = 0; 00856 uint32_t crc_size = program_size; 00857 if (offset == 0) { 00858 // Overlap with the size field 00859 00860 // Check that the data length is correct 00861 const size_t data_size = (buf[0] << (0 * 8)) | 00862 (buf[1] << (1 * 8)) | 00863 (buf[2] << (2 * 8)) | 00864 (buf[3] << (3 * 8)); 00865 if (data_size != file_size - LENGTH_SIZE - CRC_SIZE) { 00866 // Invalid data length 00867 sys_pin_mode_disabled(); 00868 return false; 00869 } 00870 size_valid = true; 00871 00872 // Don't include the length in the checksum 00873 crc_offset += LENGTH_SIZE; 00874 crc_size -= LENGTH_SIZE; 00875 } 00876 if (offset + program_size > file_size - CRC_SIZE) { 00877 // Overlap with the CRC field 00878 for (uint32_t i = 0; i < CRC_SIZE; i++) { 00879 uint32_t byte_offset = file_size - CRC_SIZE + i; 00880 if ((byte_offset >= offset) && (byte_offset < offset + program_size)) { 00881 uint32_t buf_pos = byte_offset - offset; 00882 stored_crc |= buf[buf_pos] << (i * 8); 00883 00884 // Don't include the stored CRC in the CRC 00885 crc_size--; 00886 } 00887 } 00888 } 00889 if (ct.compute_partial(buf + crc_offset, crc_size, &crc) != 0) { 00890 sys_pin_mode_disabled(); 00891 return false; 00892 } 00893 00894 // Write data to file 00895 const uint32_t addr = start + offset; 00896 if (addr % erase_size == 0) { 00897 if (flash.erase(addr, erase_size) != BD_ERROR_OK) { 00898 sys_pin_mode_disabled(); 00899 return false; 00900 } 00901 } 00902 if (flash.program(buf, addr, read_size) != BD_ERROR_OK) { 00903 sys_pin_mode_disabled(); 00904 return false; 00905 } 00906 00907 offset += program_size; 00908 00909 const uint8_t percent_done = (offset * 100) / file_size; 00910 if (percent_done != prev_percent_done) { 00911 progress(percent_done); 00912 prev_percent_done = percent_done; 00913 } 00914 } 00915 00916 // Check that everything was good and if so switch active bank 00917 if (!size_valid) { 00918 sys_pin_mode_disabled(); 00919 return false; 00920 } 00921 if (ct.compute_partial_stop(&crc) != 0) { 00922 sys_pin_mode_disabled(); 00923 return false; 00924 } 00925 if (crc != stored_crc) { 00926 sys_pin_mode_disabled(); 00927 return false; 00928 } 00929 if (!_firmware_set_active_bank(flash, !second_bank_active)) { 00930 sys_pin_mode_disabled(); 00931 return false; 00932 } 00933 00934 progress(100); 00935 00936 sys_pin_mode_disabled(); 00937 return true; 00938 } 00939 00940 void MbedTester::pin_map_set(PinName physical, LogicalPin logical) 00941 { 00942 int index = _form_factor.index(physical); 00943 if (index < 0) { 00944 error("Pin %i not in form factor", physical); 00945 return; 00946 } 00947 if (logical >= LogicalPinTotal) { 00948 error("Invalid logical pin %i", logical); 00949 return; 00950 } 00951 pin_map_index(index, logical); 00952 } 00953 00954 void MbedTester::pin_map_reset() 00955 { 00956 for (uint32_t i = 0; i < sizeof(_mapping) / sizeof(_mapping[0]); i++) { 00957 _mapping[i] = PHYSICAL_NC; 00958 } 00959 00960 uint8_t pin_buf[PHYSICAL_PINS + LOGICAL_PINS]; 00961 memset(pin_buf, 0xFF, sizeof(pin_buf)); 00962 write(TESTER_REMAP, pin_buf, sizeof(pin_buf)); 00963 } 00964 00965 void MbedTester::peripherals_reset() 00966 { 00967 uint8_t buf = TESTER_CONTROL_RESET_PERIPHERALS; 00968 write(TESTER_CONTROL_RESET, &buf, sizeof(buf)); 00969 } 00970 00971 void MbedTester::reset() 00972 { 00973 // Reset pullup settings 00974 pin_pull_reset_all(); 00975 00976 // Reset the FPGA 00977 uint8_t buf = TESTER_CONTROL_RESET_ALL; 00978 write(TESTER_CONTROL_RESET, &buf, sizeof(buf)); 00979 00980 // Reset the pinmap 00981 // NOTE - this is only needed for compatibility with 00982 // older firmware which resets the mapping 00983 // of all pins to 0x00 rather than 0xFF. 00984 pin_map_reset(); 00985 00986 // Reset internal state variables 00987 _reset(); 00988 } 00989 00990 void MbedTester::reprogram() 00991 { 00992 // Trigger reprogramming 00993 uint8_t buf = TESTER_CONTROL_REPROGRAM; 00994 write(TESTER_CONTROL_RESET, &buf, sizeof(buf)); 00995 00996 // Reset internal state variables 00997 _reset(); 00998 } 00999 01000 uint32_t MbedTester::version() 01001 { 01002 uint32_t software_version; 01003 01004 read(TESTER_CONTROL_VERSION, (uint8_t *)&software_version, sizeof(software_version)); 01005 01006 return software_version; 01007 } 01008 01009 void MbedTester::select_peripheral(Peripheral peripheral) 01010 { 01011 uint8_t data = peripheral; 01012 write(TESTER_PERIPHERAL_SELECT, &data, sizeof(data)); 01013 } 01014 01015 void MbedTester::pin_pull_reset_all() 01016 { 01017 _init_io_exp_rst_flag = 1; 01018 sys_pin_write(I2CReset, 0, true); 01019 wait_us(1); 01020 sys_pin_write(I2CReset, 0, false); 01021 } 01022 01023 int MbedTester::pin_set_pull(PinName pin, PullMode mode) 01024 { 01025 int index = _form_factor.index(pin); 01026 if ((index < 0) || (index > 127)) { 01027 error("Pin %i not in form factor", pin); 01028 return -1; 01029 } 01030 01031 return pin_set_pull_index(index, mode); 01032 } 01033 01034 int MbedTester::pin_set_pull_index(int index, PullMode mode) 01035 { 01036 // Reset IO expanders once after Mbed reset if user attempts 01037 // to read/write them without explicitly reseting them 01038 if (_init_io_exp_rst_flag == 0) { 01039 pin_pull_reset_all(); 01040 } 01041 uint8_t chip_num;//can be 0-5 01042 uint16_t dev_addr;//can be 0x44 or 0x46 01043 uint8_t port_num;//can be 0-23 01044 uint8_t output_port_reg;//can be 4, 5, or 6 01045 uint8_t config_reg;//can be 12, 13, or 14 01046 uint8_t reg_bit;//can be 0-7 01047 uint8_t cmd0[2];//for writing configuration register 01048 uint8_t cmd1[2];//for writing output port register 01049 uint8_t i2c_index;//can be 0, 1, or 2 for TESTER_SYS_IO_MODE_I2C_IO_EXPANDER0/1/2 01050 01051 chip_num = index / 24; 01052 if ((chip_num == 0) || (chip_num == 1)) { 01053 i2c_index = 0; 01054 } else if ((chip_num == 2) || (chip_num == 3)) { 01055 i2c_index = 1; 01056 } else if ((chip_num == 4) || (chip_num == 5)) { 01057 i2c_index = 2; 01058 } else { 01059 error("Corrupt index %i, should be 0-127\r\n", index); 01060 return -1; 01061 } 01062 dev_addr = (chip_num % 2) ? 0x44 : 0x46; 01063 port_num = index % 24; 01064 output_port_reg = 4 + (port_num / 8); 01065 config_reg = 12 + (port_num / 8); 01066 reg_bit = port_num % 8; 01067 01068 uint8_t read_config_byte[1]; 01069 uint8_t read_output_byte[1]; 01070 if (io_expander_i2c_read(i2c_index, dev_addr, config_reg, read_config_byte, 1) != 0) { 01071 return -1; 01072 } 01073 if (io_expander_i2c_read(i2c_index, dev_addr, output_port_reg, read_output_byte, 1) != 0) { 01074 return -1; 01075 } 01076 cmd0[0] = config_reg; 01077 if ((mode == PullDown) || (mode == PullUp)) { 01078 cmd0[1] = read_config_byte[0] & ~(1 << reg_bit); 01079 cmd1[0] = output_port_reg; 01080 if (mode == PullDown) { 01081 cmd1[1] = read_output_byte[0] & ~(1 << reg_bit); 01082 } else if (mode == PullUp) { 01083 cmd1[1] = read_output_byte[0] | (1 << reg_bit); 01084 } 01085 } else if (mode == PullNone) { 01086 cmd0[1] = read_config_byte[0] | (1 << reg_bit); 01087 } 01088 01089 //write configuration register for all 3 modes 01090 if (io_expander_i2c_write(i2c_index, dev_addr, cmd0, 2) != 0) { 01091 return -1; 01092 } 01093 //only write output register for pulldown and pullup 01094 if ((mode == PullDown) || (mode == PullUp)) { 01095 if (io_expander_i2c_write(i2c_index, dev_addr, cmd1, 2) != 0) { 01096 return -1; 01097 } 01098 } 01099 return 0; 01100 } 01101 01102 uint8_t MbedTester::io_expander_read(PinName pin, IOExpanderReg reg_type) 01103 { 01104 int index = _form_factor.index(pin); 01105 01106 return io_expander_read_index(index, reg_type); 01107 } 01108 01109 uint8_t MbedTester::io_expander_read_index(int index, IOExpanderReg reg_type) 01110 { 01111 // Reset IO expanders once after Mbed reset if user attempts 01112 // to read/write them without explicitly reseting them 01113 if (_init_io_exp_rst_flag == 0) { 01114 pin_pull_reset_all(); 01115 } 01116 uint8_t read_byte[1] = {0}; 01117 uint8_t chip_num;//can be 0-5 01118 uint16_t dev_addr;//can be 0x44 or 0x46 01119 uint8_t port_num;//can be 0-23 01120 uint8_t input_port_reg;//can be 0, 1, or 2 01121 uint8_t output_port_reg;//can be 4, 5, or 6 01122 uint8_t config_reg;//can be 12, 13, or 14 01123 uint8_t reg_bit;//can be 0-7 01124 uint8_t i2c_index; 01125 01126 chip_num = index / 24; 01127 if ((chip_num == 0) || (chip_num == 1)) { 01128 i2c_index = 0; 01129 } else if ((chip_num == 2) || (chip_num == 3)) { 01130 i2c_index = 1; 01131 } else if ((chip_num == 4) || (chip_num == 5)) { 01132 i2c_index = 2; 01133 } else { 01134 i2c_index = 0xFF; 01135 error("Invalid pin index, index should be in the range of 0-127"); 01136 } 01137 dev_addr = (chip_num % 2) ? 0x44 : 0x46; 01138 port_num = index % 24; 01139 input_port_reg = (port_num / 8); 01140 output_port_reg = 4 + (port_num / 8); 01141 config_reg = 12 + (port_num / 8); 01142 reg_bit = port_num % 8; 01143 uint8_t reg; 01144 if (reg_type == RegInput) { 01145 reg = input_port_reg; 01146 } else if (reg_type == RegOutput) { 01147 reg = output_port_reg; 01148 } else if (reg_type == RegConfig) { 01149 reg = config_reg; 01150 } else { 01151 reg = 0xFF; 01152 error("Invalid register type, should be: INPUT, OUTPUT, or RegConfig"); 01153 } 01154 01155 int read_success = io_expander_i2c_read(i2c_index, dev_addr, reg, read_byte, 1); 01156 MBED_ASSERT(read_success == 0); 01157 uint8_t bit = (read_byte[0] & (1 << reg_bit)) >> reg_bit; 01158 return bit; 01159 } 01160 01161 int MbedTester::io_expander_i2c_read(uint8_t i2c_index, uint8_t dev_addr, uint8_t start_reg, uint8_t *data, int length) 01162 { 01163 _update_control_pins(); 01164 //sda_in = _miso_index 01165 //sda_val = _aux_index 01166 //scl_in = _mosi_index (PHYSICAL_NC) 01167 //scl_val = _clk_index 01168 mbed::DigitalInOut *sda_in = _miso; 01169 mbed::DigitalInOut *sda_val = _aux; 01170 mbed::DigitalInOut *scl_val = _clk; 01171 sda_in->input(); 01172 sda_val->output(); 01173 *sda_val = 1; 01174 scl_val->output(); 01175 sys_pin_mode_i2c_io_expander(i2c_index, _miso_index, _aux_index, PHYSICAL_NC, _clk_index); 01176 01177 //start condition 01178 *scl_val = 1; 01179 wait_ns(2500); 01180 *sda_val = 0; 01181 wait_ns(2500); 01182 01183 // begin writing data, dev_addr first 01184 uint8_t send_bit; 01185 for (int j = 0; j < 2; j += 1) { 01186 *scl_val = 0; 01187 *sda_val = 0; 01188 wait_ns(2500); 01189 for (int i = 7; i > -1; i -= 1) { 01190 if (j == 0) { 01191 send_bit = (dev_addr & (1 << i)) >> i; 01192 } else { 01193 send_bit = (start_reg & (1 << i)) >> i; 01194 } 01195 *sda_val = send_bit; 01196 wait_ns(500); 01197 01198 *scl_val = 1; 01199 wait_ns(2500); 01200 *scl_val = 0; 01201 wait_ns(1000); 01202 *sda_val = 0; 01203 wait_ns(1000); 01204 } 01205 // receive ACK from IO extender 01206 *sda_val = 1;//make sda high z to receive ACK 01207 //clk the ACK 01208 *scl_val = 1; 01209 //read sda to check for ACK or NACK 01210 if (*sda_in) { 01211 return -1;//NACK - write failed 01212 } 01213 wait_ns(2500); 01214 *scl_val = 0; 01215 wait_ns(2500); 01216 } 01217 01218 //start condition 01219 *sda_val = 1; 01220 *scl_val = 1; 01221 wait_ns(2500); 01222 *sda_val = 0; 01223 wait_ns(2500); 01224 01225 // begin reading data, write (dev_addr | 1) first 01226 dev_addr |= 1; 01227 for (int j = -1; j < length; j += 1) { 01228 uint8_t read_byte = 0; 01229 for (int i = 7; i > -1; i -= 1) { 01230 if (j == -1) { 01231 *scl_val = 0; 01232 *sda_val = 0; 01233 send_bit = (dev_addr & (1 << i)) >> i; 01234 *sda_val = send_bit; 01235 wait_ns(500); 01236 01237 *scl_val = 1; 01238 wait_ns(2500); 01239 *scl_val = 0; 01240 wait_ns(1000); 01241 *sda_val = 0; 01242 wait_ns(1000); 01243 } else { 01244 *scl_val = 1; 01245 read_byte |= (*sda_in << i); 01246 wait_ns(2500); 01247 *scl_val = 0; 01248 wait_ns(2500); 01249 } 01250 } 01251 if (j > -1) { 01252 data[j] = read_byte; 01253 } 01254 if (j == -1) { 01255 // receive ACK from IO extender 01256 *sda_val = 1;//make sda high z to receive ACK 01257 //clk the ACK 01258 *scl_val = 1; 01259 //read sda to check for ACK or NACK 01260 if (*sda_in) { 01261 return -1;//NACK - write failed 01262 } 01263 wait_ns(2500); 01264 *scl_val = 0; 01265 wait_ns(2500); 01266 } else { 01267 if (j == (length - 1)) { //NACK to signal end of read 01268 *sda_val = 1; 01269 wait_ns(1000); 01270 *scl_val = 1; 01271 wait_ns(2500); 01272 *scl_val = 0; 01273 wait_ns(1500); 01274 } else {//ACK to signal read will continue 01275 *sda_val = 0; 01276 wait_ns(1000); 01277 *scl_val = 1; 01278 wait_ns(2500); 01279 *scl_val = 0; 01280 wait_ns(500); 01281 *sda_val = 1; 01282 wait_ns(1000); 01283 } 01284 } 01285 } 01286 01287 //stop condition 01288 *sda_val = 0; 01289 wait_ns(2500); 01290 *scl_val = 1; 01291 wait_ns(2500); 01292 *sda_val = 1; 01293 wait_ns(2500); 01294 01295 sys_pin_mode_disabled(); 01296 01297 return 0; 01298 } 01299 01300 int MbedTester::io_expander_i2c_write(uint8_t i2c_index, uint8_t dev_addr, uint8_t *data, int length) 01301 { 01302 _update_control_pins(); 01303 //sda_in = _miso_index 01304 //sda_val = _aux_index 01305 //scl_in = _mosi_index (PHYSICAL_NC) 01306 //scl_val = _clk_index 01307 mbed::DigitalInOut *sda_in = _miso; 01308 mbed::DigitalInOut *sda_val = _aux; 01309 mbed::DigitalInOut *scl_val = _clk; 01310 sda_in->input(); 01311 sda_val->output(); 01312 *sda_val = 1; 01313 scl_val->output(); 01314 sys_pin_mode_i2c_io_expander(i2c_index, _miso_index, _aux_index, PHYSICAL_NC, _clk_index); 01315 01316 //start condition 01317 *scl_val = 1; 01318 wait_ns(2500); 01319 *sda_val = 0; 01320 wait_ns(2500); 01321 01322 // begin writing data, dev_addr first 01323 uint8_t send_bit; 01324 for (int j = -1; j < length; j += 1) { 01325 *scl_val = 0; 01326 *sda_val = 0; 01327 for (int i = 7; i > -1; i -= 1) { 01328 if (j == -1) { 01329 send_bit = (dev_addr & (1 << i)) >> i; 01330 } else { 01331 send_bit = (data[j] & (1 << i)) >> i; 01332 } 01333 01334 *sda_val = send_bit; 01335 wait_ns(500); 01336 01337 *scl_val = 1; 01338 wait_ns(2500); 01339 *scl_val = 0; 01340 wait_ns(1000); 01341 *sda_val = 0; 01342 wait_ns(1000); 01343 } 01344 // receive ACK from IO extender 01345 *sda_val = 1;//make sda high z to receive ACK 01346 //clk the ACK 01347 *scl_val = 1; 01348 //read sda to check for ACK or NACK 01349 if (*sda_in) { 01350 return -1;//NACK - write failed 01351 } 01352 wait_ns(2500); 01353 *scl_val = 0; 01354 wait_ns(2500); 01355 } 01356 01357 //stop condition 01358 *sda_val = 0; 01359 wait_ns(2500); 01360 *scl_val = 1; 01361 wait_ns(2500); 01362 *sda_val = 1; 01363 wait_ns(2500); 01364 01365 sys_pin_mode_disabled(); 01366 01367 return 0; 01368 } 01369 01370 int MbedTester::pin_set_pull_bb(PinName pin, PullMode mode) 01371 { 01372 int index = _form_factor.index(pin); 01373 if ((index < 0) || (index > 127)) { 01374 error("Pin %i not in form factor", pin); 01375 return -1; 01376 } 01377 uint8_t chip_num;//can be 0-5 01378 SystemPin sda;//can be I2CSda0, I2CSda1, or I2CSda2 01379 SystemPin scl;//can be I2CScl0, I2CScl1, or I2CScl2 01380 uint16_t dev_addr;//can be 0x44 or 0x46 01381 uint8_t port_num;//can be 0-23 01382 uint8_t output_port_reg;//can be 4, 5, or 6 01383 uint8_t config_reg;//can be 12, 13, or 14 01384 uint8_t reg_bit;//can be 0-7 01385 uint8_t cmd0[2];//for writing configuration register 01386 uint8_t cmd1[2];//for writing output port register 01387 01388 chip_num = index / 24; 01389 if ((chip_num == 0) || (chip_num == 1)) { 01390 sda = I2CSda0; 01391 scl = I2CScl0; 01392 } else if ((chip_num == 2) || (chip_num == 3)) { 01393 sda = I2CSda1; 01394 scl = I2CScl1; 01395 } else if ((chip_num == 4) || (chip_num == 5)) { 01396 sda = I2CSda2; 01397 scl = I2CScl2; 01398 } else { 01399 error("Pin %i not in form factor", pin); 01400 return -1; 01401 } 01402 dev_addr = (chip_num % 2) ? 0x44 : 0x46; 01403 port_num = index % 24; 01404 output_port_reg = 4 + (port_num / 8); 01405 config_reg = 12 + (port_num / 8); 01406 reg_bit = port_num % 8; 01407 01408 uint8_t read_config_byte[1]; 01409 uint8_t read_output_byte[1]; 01410 if (io_expander_i2c_read_bb(sda, scl, dev_addr, config_reg, read_config_byte, 1) != 0) { 01411 return -1; 01412 } 01413 if (io_expander_i2c_read_bb(sda, scl, dev_addr, output_port_reg, read_output_byte, 1) != 0) { 01414 return -1; 01415 } 01416 cmd0[0] = config_reg; 01417 if ((mode == PullDown) || (mode == PullUp)) { 01418 cmd0[1] = read_config_byte[0] & ~(1 << reg_bit); 01419 cmd1[0] = output_port_reg; 01420 if (mode == PullDown) { 01421 cmd1[1] = read_output_byte[0] & ~(1 << reg_bit); 01422 } else if (mode == PullUp) { 01423 cmd1[1] = read_output_byte[0] | (1 << reg_bit); 01424 } 01425 } else if (mode == PullNone) { 01426 cmd0[1] = read_config_byte[0] | (1 << reg_bit); 01427 } 01428 01429 //write configuration register for all 3 modes 01430 if (io_expander_i2c_write_bb(sda, scl, dev_addr, cmd0, 2) != 0) { 01431 return -1; 01432 } 01433 //only write output register for pulldown and pullup 01434 if ((mode == PullDown) || (mode == PullUp)) { 01435 if (io_expander_i2c_write_bb(sda, scl, dev_addr, cmd1, 2) != 0) { 01436 return -1; 01437 } 01438 } 01439 return 0; 01440 } 01441 01442 uint8_t MbedTester::io_expander_read_bb(PinName pin, IOExpanderReg reg_type) 01443 { 01444 int index = _form_factor.index(pin); 01445 uint8_t read_byte[1] = {0}; 01446 uint8_t chip_num;//can be 0-5 01447 SystemPin sda;//can be I2CSda0, I2CSda1, or I2CSda2 01448 SystemPin scl;//can be I2CScl0, I2CScl1, or I2CScl2 01449 uint16_t dev_addr;//can be 0x44 or 0x46 01450 uint8_t port_num;//can be 0-23 01451 uint8_t input_port_reg;//can be 0, 1, or 2 01452 uint8_t output_port_reg;//can be 4, 5, or 6 01453 uint8_t config_reg;//can be 12, 13, or 14 01454 uint8_t reg_bit;//can be 0-7 01455 01456 chip_num = index / 24; 01457 if ((chip_num == 0) || (chip_num == 1)) { 01458 sda = I2CSda0; 01459 scl = I2CScl0; 01460 } else if ((chip_num == 2) || (chip_num == 3)) { 01461 sda = I2CSda1; 01462 scl = I2CScl1; 01463 } else if ((chip_num == 4) || (chip_num == 5)) { 01464 sda = I2CSda2; 01465 scl = I2CScl2; 01466 } else { 01467 sda = (SystemPin) - 1; 01468 scl = (SystemPin) - 1; 01469 error("Invalid pin index, index should be in the range of 0-127"); 01470 } 01471 01472 dev_addr = (chip_num % 2) ? 0x44 : 0x46; 01473 port_num = index % 24; 01474 input_port_reg = (port_num / 8); 01475 output_port_reg = 4 + (port_num / 8); 01476 config_reg = 12 + (port_num / 8); 01477 reg_bit = port_num % 8; 01478 uint8_t reg; 01479 if (reg_type == RegInput) { 01480 reg = input_port_reg; 01481 } else if (reg_type == RegOutput) { 01482 reg = output_port_reg; 01483 } else if (reg_type == RegConfig) { 01484 reg = config_reg; 01485 } else { 01486 reg = 0xFF; 01487 error("Invalid register type, should be: INPUT, OUTPUT, or CONFIG"); 01488 } 01489 01490 int read_success = io_expander_i2c_read_bb(sda, scl, dev_addr, reg, read_byte, 1); 01491 MBED_ASSERT(read_success == 0); 01492 uint8_t bit = (read_byte[0] & (1 << reg_bit)) >> reg_bit; 01493 return bit; 01494 } 01495 01496 int MbedTester::io_expander_i2c_read_bb(SystemPin sda, SystemPin scl, uint8_t dev_addr, uint8_t start_reg, uint8_t *data, int length) 01497 { 01498 //start condition 01499 sys_pin_write(sda, 0, false); 01500 sys_pin_write(scl, 0, false); 01501 sys_pin_write(sda, 0, true); 01502 01503 // begin writing data, dev_addr first 01504 uint8_t send_bit; 01505 for (int j = 0; j < 2; j += 1) { 01506 sys_pin_write(scl, 0, true); 01507 sys_pin_write(sda, 0, true); 01508 for (int i = 7; i > -1; i -= 1) { 01509 if (j == 0) { 01510 send_bit = (dev_addr & (1 << i)) >> i; 01511 } else { 01512 send_bit = (start_reg & (1 << i)) >> i; 01513 } 01514 if (send_bit == 1) { 01515 sys_pin_write(sda, 0, false); 01516 } else if (send_bit == 0) { 01517 sys_pin_write(sda, 0, true); 01518 } 01519 sys_pin_write(scl, 0, false); 01520 sys_pin_write(scl, 0, true); 01521 sys_pin_write(sda, 0, true); 01522 } 01523 // receive ACK from IO extender 01524 sys_pin_write(sda, 0, false);//make sda high z to receive ACK 01525 //clk the ACK 01526 sys_pin_write(scl, 0, false); 01527 //read sda to check for ACK or NACK 01528 if (sys_pin_read(sda)) { 01529 return -1;//NACK - write failed 01530 } 01531 sys_pin_write(scl, 0, true); 01532 } 01533 01534 //start condition 01535 sys_pin_write(sda, 0, false); 01536 sys_pin_write(scl, 0, false); 01537 sys_pin_write(sda, 0, true); 01538 01539 // begin reading data, write (dev_addr | 1) first 01540 dev_addr |= 1; 01541 for (int j = -1; j < length; j += 1) { 01542 uint8_t read_byte = 0; 01543 for (int i = 7; i > -1; i -= 1) { 01544 if (j == -1) { 01545 sys_pin_write(scl, 0, true); 01546 sys_pin_write(sda, 0, true); 01547 send_bit = (dev_addr & (1 << i)) >> i; 01548 if (send_bit == 1) { 01549 sys_pin_write(sda, 0, false); 01550 } else if (send_bit == 0) { 01551 sys_pin_write(sda, 0, true); 01552 } 01553 sys_pin_write(scl, 0, false); 01554 sys_pin_write(scl, 0, true); 01555 sys_pin_write(sda, 0, true); 01556 } else { 01557 sys_pin_write(scl, 0, false); 01558 read_byte |= (sys_pin_read(sda) << i); 01559 sys_pin_write(scl, 0, true); 01560 } 01561 } 01562 if (j > -1) { 01563 data[j] = read_byte; 01564 } 01565 if (j == -1) { 01566 // receive ACK from IO extender 01567 sys_pin_write(sda, 0, false);//make sda high z to receive ACK 01568 //clk the ACK 01569 sys_pin_write(scl, 0, false); 01570 //read sda to check for ACK or NACK 01571 if (sys_pin_read(sda)) { 01572 return -1;//NACK - write failed 01573 } 01574 sys_pin_write(scl, 0, true); 01575 } else { 01576 if (j == (length - 1)) { //NACK to signal end of read 01577 sys_pin_write(sda, 0, false); 01578 sys_pin_write(scl, 0, false); 01579 sys_pin_write(scl, 0, true); 01580 } else {//ACK to signal read will continue 01581 sys_pin_write(sda, 0, true); 01582 sys_pin_write(scl, 0, false); 01583 sys_pin_write(scl, 0, true); 01584 sys_pin_write(sda, 0, false); 01585 } 01586 } 01587 } 01588 01589 //stop condition 01590 sys_pin_write(sda, 0, true); 01591 sys_pin_write(scl, 0, false); 01592 sys_pin_write(sda, 0, false); 01593 return 0; 01594 } 01595 01596 int MbedTester::io_expander_i2c_write_bb(SystemPin sda, SystemPin scl, uint8_t dev_addr, uint8_t *data, int length) 01597 { 01598 //start condition 01599 sys_pin_write(sda, 0, false); 01600 sys_pin_write(scl, 0, false); 01601 sys_pin_write(sda, 0, true); 01602 01603 // begin writing data, dev_addr first 01604 uint8_t send_bit; 01605 for (int j = -1; j < length; j += 1) { 01606 sys_pin_write(scl, 0, true); 01607 sys_pin_write(sda, 0, true); 01608 for (int i = 7; i > -1; i -= 1) { 01609 if (j == -1) { 01610 send_bit = (dev_addr & (1 << i)) >> i; 01611 } else { 01612 send_bit = (data[j] & (1 << i)) >> i; 01613 } 01614 if (send_bit == 1) { 01615 sys_pin_write(sda, 0, false); 01616 } else if (send_bit == 0) { 01617 sys_pin_write(sda, 0, true); 01618 } 01619 sys_pin_write(scl, 0, false); 01620 sys_pin_write(scl, 0, true); 01621 sys_pin_write(sda, 0, true); 01622 } 01623 // receive ACK from IO extender 01624 sys_pin_write(sda, 0, false);//make sda high z to receive ACK 01625 //clk the ACK 01626 sys_pin_write(scl, 0, false); 01627 //read sda to check for ACK or NACK 01628 if (sys_pin_read(sda)) { 01629 return -1;//NACK - write failed 01630 } 01631 sys_pin_write(scl, 0, true); 01632 } 01633 01634 //stop condition 01635 sys_pin_write(sda, 0, true); 01636 sys_pin_write(scl, 0, false); 01637 sys_pin_write(sda, 0, false); 01638 return 0; 01639 } 01640 01641 void MbedTester::set_analog_out(bool enable, float voltage) 01642 { 01643 uint32_t cycles_high = (int)(100 * voltage); 01644 uint32_t period = 100; 01645 set_pwm_period_and_cycles_high(period, cycles_high); 01646 set_pwm_enable(enable); 01647 } 01648 01649 int MbedTester::set_mux_addr(PinName pin) 01650 { 01651 int index = _form_factor.index(pin); 01652 if ((index < 0) || (index > 127)) { 01653 error("Pin %i not in form factor", pin); 01654 return -1; 01655 } 01656 01657 return set_mux_addr_index(index); 01658 } 01659 01660 int MbedTester::set_mux_addr_index(int index) 01661 { 01662 sys_pin_write(AnalogMuxAddr0, index & 0x01, true); 01663 sys_pin_write(AnalogMuxAddr1, (index & 0x02) >> 1, true); 01664 sys_pin_write(AnalogMuxAddr2, (index & 0x04) >> 2, true); 01665 sys_pin_write(AnalogMuxAddr3, (index & 0x08) >> 3, true); 01666 sys_pin_write(AnalogMuxAddr4, (index & 0x10) >> 4, true); 01667 sys_pin_write(AnalogMuxAddr5, (index & 0x20) >> 5, true); 01668 sys_pin_write(AnalogMuxAddr6, (index & 0x40) >> 6, true); 01669 sys_pin_write(AnalogMuxAddr7, (index & 0x80) >> 7, true); 01670 01671 return 0; 01672 } 01673 01674 void MbedTester::set_mux_enable(bool val) 01675 { 01676 if (val == true) { 01677 sys_pin_write(AnalogMuxEnable, 0, true);//enable analog MUXes 01678 } else if (val == false) { 01679 sys_pin_write(AnalogMuxEnable, 1, true);//disable analog MUXes 01680 } 01681 wait_us(10); 01682 } 01683 01684 void MbedTester::set_pwm_enable(bool val) 01685 { 01686 uint8_t data; 01687 if (val == true) { 01688 data = 1; 01689 } else if (val == false) { 01690 data = 0; 01691 } 01692 write(TESTER_SYS_IO_PWM_ENABLE, &data, sizeof(data)); 01693 } 01694 01695 bool MbedTester::get_pwm_enable() 01696 { 01697 uint8_t val = 0; 01698 read(TESTER_SYS_IO_PWM_ENABLE, &val, sizeof(val)); 01699 if (val == 1) { 01700 return true; 01701 } else if (val == 0) { 01702 return false; 01703 } else { 01704 error("Corrupt pwm enable value"); 01705 return false; 01706 } 01707 } 01708 01709 void MbedTester::set_pwm_period_and_cycles_high(uint32_t period, uint32_t cycles_high) 01710 { 01711 set_pwm_enable(false); 01712 uint32_t p = period - 1;//period in cycles 01713 uint32_t d = cycles_high;//number of cycles pwm out is high 01714 write(TESTER_SYS_IO_PWM_PERIOD, (uint8_t *)&p, sizeof(p)); 01715 write(TESTER_SYS_IO_PWM_CYCLES_HIGH, (uint8_t *)&d, sizeof(d)); 01716 set_pwm_enable(true); 01717 } 01718 01719 uint32_t MbedTester::get_pwm_period() 01720 { 01721 uint32_t period = 0; 01722 read(TESTER_SYS_IO_PWM_PERIOD, (uint8_t *)&period, sizeof(period)); 01723 return period + 1;//clk cycles 01724 } 01725 01726 uint8_t MbedTester::get_pwm_cycles_high() 01727 { 01728 uint8_t cycles_high = 0; 01729 read(TESTER_SYS_IO_PWM_CYCLES_HIGH, &cycles_high, sizeof(cycles_high)); 01730 return cycles_high; 01731 } 01732 01733 uint16_t MbedTester::get_analogmuxin_measurement() 01734 { 01735 rtos::ThisThread::sleep_for(1);//wait for value to stabalize 01736 //take snapshot of conversion value to make safe for reading 01737 set_snapshot(); 01738 uint16_t an_mux_analogin_measurement = 0; 01739 read(TESTER_SYS_IO_AN_MUX_ANALOGIN_MEASUREMENT, (uint8_t *)&an_mux_analogin_measurement, sizeof(an_mux_analogin_measurement)); 01740 return an_mux_analogin_measurement; 01741 } 01742 01743 uint16_t MbedTester::get_anin_measurement(int index) 01744 { 01745 //check index is in bounds 01746 if ((index < 0) || (index >= ANALOG_COUNT)) { 01747 error("AnalogIn index is out of bounds"); 01748 } 01749 //take snapshot of conversion value to make safe for reading 01750 set_snapshot(); 01751 uint16_t anin_measurement = 0; 01752 read((TESTER_SYS_IO_ANIN0_MEASUREMENT + (index * 10)), (uint8_t *)&anin_measurement, sizeof(anin_measurement)); //10 because sizeof measurement + sizeof measurements_sum = 10 01753 return anin_measurement; 01754 } 01755 01756 void MbedTester::get_anin_sum_samples_cycles(int index, uint64_t *sum, uint32_t *samples, uint64_t *cycles) 01757 { 01758 //check index is in bounds 01759 if ((index < 0) || (index >= ANALOG_COUNT)) { 01760 error("AnalogIn index is out of bounds"); 01761 } 01762 //take snapshot of the sum/samples/cycles so that all 3 values are correct in relation to each other 01763 set_snapshot(); 01764 read((TESTER_SYS_IO_ANIN0_MEASUREMENTS_SUM + (index * 10)), (uint8_t *)sum, sizeof(*sum)); //10 because sizeof measurement + sizeof measurements_sum = 10 01765 read(TESTER_SYS_IO_NUM_POWER_SAMPLES, (uint8_t *)samples, sizeof(*samples)); 01766 read(TESTER_SYS_IO_NUM_POWER_CYCLES, (uint8_t *)cycles, sizeof(*cycles)); 01767 } 01768 01769 void MbedTester::set_snapshot() 01770 { 01771 uint8_t data = 1; 01772 write(TESTER_SYS_IO_ADC_SNAPSHOT, &data, sizeof(data)); 01773 wait_us(1); 01774 } 01775 01776 void MbedTester::set_sample_adc(bool val) 01777 { 01778 uint8_t data; 01779 if (val == true) { 01780 data = 1; 01781 } else if (val == false) { 01782 data = 0; 01783 } 01784 write(TESTER_SYS_IO_SAMPLE_ADC, &data, sizeof(data)); 01785 } 01786 01787 float MbedTester::get_analog_in() 01788 { 01789 uint16_t data = get_analogmuxin_measurement(); 01790 float data_f = (float)data / 4095.0f; 01791 return data_f; 01792 } 01793 01794 float MbedTester::get_anin_voltage(int index) 01795 { 01796 uint16_t data = get_anin_measurement(index); 01797 float data_f = (float)data / 4095.0f; 01798 return data_f; 01799 } 01800 01801 int MbedTester::gpio_read(LogicalPin gpio) 01802 { 01803 if (gpio >= LogicalPinCount) { 01804 error("Invalid pin for gpio_read"); 01805 return 0; 01806 } 01807 uint8_t data = 0; 01808 read(TESTER_GPIO + gpio, &data, sizeof(data)); 01809 return data; 01810 } 01811 01812 void MbedTester::gpio_write(LogicalPin gpio, int value, bool drive) 01813 { 01814 if (gpio >= LogicalPinCount) { 01815 error("Invalid pin for gpio_write"); 01816 return; 01817 } 01818 uint8_t data = 0; 01819 data |= value ? (1 << 0) : 0; 01820 data |= drive ? (1 << 1) : 0; 01821 write(TESTER_GPIO + gpio, &data, sizeof(data)); 01822 } 01823 01824 void MbedTester::io_metrics_start() 01825 { 01826 uint8_t data = TESTER_IO_METRICS_CTRL_RESET_BIT; 01827 write(TESTER_IO_METRICS_CTRL, &data, sizeof(data)); 01828 01829 data = TESTER_IO_METRICS_CTRL_ACTIVE_BIT; 01830 write(TESTER_IO_METRICS_CTRL, &data, sizeof(data)); 01831 } 01832 01833 void MbedTester::io_metrics_stop() 01834 { 01835 uint8_t data = 0; 01836 write(TESTER_IO_METRICS_CTRL, &data, sizeof(data)); 01837 } 01838 01839 void MbedTester::io_metrics_continue() 01840 { 01841 uint8_t data = TESTER_IO_METRICS_CTRL_ACTIVE_BIT; 01842 write(TESTER_IO_METRICS_CTRL, &data, sizeof(data)); 01843 } 01844 01845 uint32_t MbedTester::io_metrics_min_pulse_low(LogicalPin pin) 01846 { 01847 if (pin >= LogicalPinCount) { 01848 error("Invalid pin for io_metrics"); 01849 return 0; 01850 } 01851 01852 uint32_t data = 0; 01853 read(TESTER_IO_METRICS_MIN_PULSE_LOW(pin), (uint8_t *)&data, sizeof(data)); 01854 return data; 01855 } 01856 01857 uint32_t MbedTester::io_metrics_min_pulse_high(LogicalPin pin) 01858 { 01859 if (pin >= LogicalPinCount) { 01860 error("Invalid pin for io_metrics"); 01861 return 0; 01862 } 01863 01864 uint32_t data = 0; 01865 read(TESTER_IO_METRICS_MIN_PULSE_HIGH(pin), (uint8_t *)&data, sizeof(data)); 01866 return data; 01867 } 01868 01869 uint32_t MbedTester::io_metrics_max_pulse_low(LogicalPin pin) 01870 { 01871 if (pin >= LogicalPinCount) { 01872 error("Invalid pin for io_metrics"); 01873 return 0; 01874 } 01875 01876 uint32_t data = 0; 01877 read(TESTER_IO_METRICS_MAX_PULSE_LOW(pin), (uint8_t *)&data, sizeof(data)); 01878 return data; 01879 } 01880 01881 uint32_t MbedTester::io_metrics_max_pulse_high(LogicalPin pin) 01882 { 01883 if (pin >= LogicalPinCount) { 01884 error("Invalid pin for io_metrics"); 01885 return 0; 01886 } 01887 01888 uint32_t data = 0; 01889 read(TESTER_IO_METRICS_MAX_PULSE_HIGH(pin), (uint8_t *)&data, sizeof(data)); 01890 return data; 01891 } 01892 01893 uint32_t MbedTester::io_metrics_rising_edges(LogicalPin pin) 01894 { 01895 if (pin >= LogicalPinCount) { 01896 error("Invalid pin for io_metrics"); 01897 return 0; 01898 } 01899 01900 uint32_t data = 0; 01901 read(TESTER_IO_METRICS_RISING_EDGES(pin), (uint8_t *)&data, sizeof(data)); 01902 return data; 01903 } 01904 01905 uint32_t MbedTester::io_metrics_falling_edges(LogicalPin pin) 01906 { 01907 if (pin >= LogicalPinCount) { 01908 error("Invalid pin for io_metrics"); 01909 return 0; 01910 } 01911 01912 uint32_t data = 0; 01913 read(TESTER_IO_METRICS_FALLING_EDGES(pin), (uint8_t *)&data, sizeof(data)); 01914 return data; 01915 } 01916 01917 bool MbedTester::sys_pin_read(SystemPin pin) 01918 { 01919 01920 if (pin >= SystemPinCount) { 01921 error("Invalid pin for gpio_read"); 01922 return 0; 01923 } 01924 uint8_t data = 0; 01925 read(TESTER_SYS_IO + pin, &data, sizeof(data)); 01926 return data; 01927 } 01928 01929 void MbedTester::sys_pin_write(SystemPin pin, int value, bool drive) 01930 { 01931 if (pin >= SystemPinCount) { 01932 error("Invalid pin for gpio_write"); 01933 return; 01934 } 01935 uint8_t data = 0; 01936 data |= value ? (1 << 0) : 0; 01937 data |= drive ? (1 << 1) : 0; 01938 write(TESTER_SYS_IO + pin, &data, sizeof(data)); 01939 } 01940 01941 void MbedTester::sys_pin_mode_disabled() 01942 { 01943 const uint32_t base = LogicalPinTotal; 01944 01945 pin_map_index(PHYSICAL_NC, (LogicalPin)(base + 0)); 01946 pin_map_index(PHYSICAL_NC, (LogicalPin)(base + 1)); 01947 pin_map_index(PHYSICAL_NC, (LogicalPin)(base + 2)); 01948 pin_map_index(PHYSICAL_NC, (LogicalPin)(base + 3)); 01949 01950 uint8_t mode = TESTER_SYS_IO_MODE_DISABLED; 01951 write(TESTER_SYS_IO_MODE, &mode, sizeof(mode)); 01952 } 01953 01954 void MbedTester::sys_pin_mode_spi_serial_flash(PhysicalIndex mosi, PhysicalIndex miso, PhysicalIndex clk, PhysicalIndex ssel) 01955 { 01956 const uint32_t base = LogicalPinTotal; 01957 01958 pin_map_index(mosi, (LogicalPin)(base + 0)); 01959 pin_map_index(miso, (LogicalPin)(base + 1)); 01960 pin_map_index(clk, (LogicalPin)(base + 2)); 01961 pin_map_index(ssel, (LogicalPin)(base + 3)); 01962 01963 uint8_t mode = TESTER_SYS_IO_MODE_SPI_SERIAL_FLASH; 01964 write(TESTER_SYS_IO_MODE, &mode, sizeof(mode)); 01965 } 01966 01967 void MbedTester::sys_pin_mode_i2c_io_expander(int index, PhysicalIndex sda_in, PhysicalIndex sda_val, PhysicalIndex scl_in, PhysicalIndex scl_val) 01968 { 01969 const uint32_t base = LogicalPinTotal; 01970 01971 pin_map_index(sda_in, (LogicalPin)(base + 0)); 01972 pin_map_index(sda_val, (LogicalPin)(base + 1)); 01973 pin_map_index(scl_in, (LogicalPin)(base + 2)); 01974 pin_map_index(scl_val, (LogicalPin)(base + 3)); 01975 01976 uint8_t mode = 0; 01977 if (index == 0) { 01978 mode = TESTER_SYS_IO_MODE_I2C_IO_EXPANDER0; 01979 } else if (index == 1) { 01980 mode = TESTER_SYS_IO_MODE_I2C_IO_EXPANDER1; 01981 } else if (index == 2) { 01982 mode = TESTER_SYS_IO_MODE_I2C_IO_EXPANDER2; 01983 } else { 01984 error("Invalid index for sys_pin_mode_i2c_io_expander"); 01985 } 01986 01987 write(TESTER_SYS_IO_MODE, &mode, sizeof(mode)); 01988 } 01989 01990 void MbedTester::pin_map_index(PhysicalIndex physical_index, LogicalPin logical) 01991 { 01992 uint8_t remap; 01993 if ((physical_index >= PHYSICAL_PINS) && (physical_index != PHYSICAL_NC)) { 01994 error("Invalid physical pin index %i", physical_index); 01995 return; 01996 } 01997 if (logical >= sizeof(_mapping) / sizeof(_mapping[0])) { 01998 error("Invalid logical pin %i", logical); 01999 return; 02000 } 02001 02002 // Unmap the previous pin if it had been mapped 02003 if (_mapping[logical] < PHYSICAL_PINS) { 02004 remap = PHYSICAL_NC; 02005 write(TESTER_REMAP + _mapping[logical], &remap, sizeof(remap)); 02006 } 02007 _mapping[logical] = physical_index; 02008 02009 // Remap physical pin if it is not PHYSICAL_NC 02010 if (physical_index < PHYSICAL_PINS) { 02011 remap = logical; 02012 write(TESTER_REMAP + physical_index, &remap, sizeof(remap)); 02013 } 02014 // Remap logical pin 02015 remap = physical_index; 02016 write(TESTER_REMAP + PHYSICAL_PINS + logical, &remap, sizeof(remap)); 02017 } 02018 02019 void MbedTester::write(uint32_t addr, const uint8_t *data, uint32_t size) 02020 { 02021 _update_control_pins(); 02022 02023 mbed_tester_command(_clk, _mosi, _miso, _miso_index, addr, true, (uint8_t *)data, size); 02024 } 02025 02026 void MbedTester::read(uint32_t addr, uint8_t *data, uint32_t size) 02027 { 02028 _update_control_pins(); 02029 02030 mbed_tester_command(_clk, _mosi, _miso, _miso_index, addr, false, data, size); 02031 } 02032 02033 bool MbedTester::self_test_all() 02034 { 02035 return self_test_control_channels() && self_test_control_miso(); 02036 } 02037 02038 bool MbedTester::self_test_control_channels() 02039 { 02040 for (uint32_t i = 0; i < _form_factor.count() / 2; i++) { 02041 const int clk_index = i * 2 + 0; 02042 const int mosi_index = i * 2 + 1; 02043 const PinName clk = _form_factor.get(clk_index); 02044 const PinName mosi = _form_factor.get(mosi_index); 02045 02046 // Check if the control pair is allowed and skip if it is not 02047 if (_exclude_pins.has_pin(clk) || _exclude_pins.has_pin(mosi)) { 02048 mbed_tester_printf("Skipping pin indexes clk=%i, mosi=%i\r\n", i * 2 + 0, i * 2 + 1); 02049 continue; 02050 } 02051 02052 // Find a pin to use as miso 02053 int miso_index = 0; 02054 PinName miso = NC; 02055 DynamicPinList more_restricted(_exclude_pins); 02056 more_restricted.add(clk); 02057 more_restricted.add(mosi); 02058 for (uint32_t j = 0; j < _form_factor.count(); j++) { 02059 miso_index = j; 02060 const PinName temp = _form_factor.get(miso_index); 02061 if (!more_restricted.has_pin(temp)) { 02062 miso = temp; 02063 break; 02064 } 02065 } 02066 if (miso == NC) { 02067 set_control_pins_auto(); 02068 return false; 02069 } 02070 02071 // Find a pin to use as aux 02072 int aux_index = 0; 02073 PinName aux = NC; 02074 more_restricted.add(miso); 02075 for (uint32_t j = 0; j < _form_factor.count(); j++) { 02076 aux_index = j; 02077 const PinName temp = _form_factor.get(aux_index); 02078 if (!more_restricted.has_pin(temp)) { 02079 aux = temp; 02080 break; 02081 } 02082 } 02083 if (aux == NC) { 02084 set_control_pins_auto(); 02085 return false; 02086 } 02087 02088 // Write and read back a value 02089 mbed_tester_printf("Testing clk_index=%2i, mosi_index=%2i, miso_index=%2i, aux_index=%2i\r\n", clk_index, mosi_index, miso_index, aux_index); 02090 set_control_pins_manual(clk, mosi, miso, aux); 02091 if (!self_test_control_current()) { 02092 mbed_tester_printf(" Fail\r\n"); 02093 set_control_pins_auto(); 02094 return false; 02095 } 02096 mbed_tester_printf(" Pass\r\n"); 02097 } 02098 02099 set_control_pins_auto(); 02100 return true; 02101 } 02102 02103 bool MbedTester::self_test_control_miso() 02104 { 02105 for (uint32_t i = 0; i < _form_factor.count(); i++) { 02106 const int miso_index = i; 02107 const PinName miso = _form_factor.get(miso_index); 02108 02109 if (_exclude_pins.has_pin(miso)) { 02110 mbed_tester_printf("Skipping miso index %i\r\n", i); 02111 continue; 02112 } 02113 02114 // Find pins to use as clk and mosi 02115 int clk_index = 0; 02116 int mosi_index = 0; 02117 PinName clk = NC; 02118 PinName mosi = NC; 02119 DynamicPinList more_restricted(_exclude_pins); 02120 more_restricted.add(miso); 02121 for (uint32_t j = 0; j < _form_factor.count() / 2; j++) { 02122 clk_index = j * 2 + 0; 02123 mosi_index = j * 2 + 1; 02124 const PinName possible_clk = _form_factor.get(clk_index); 02125 const PinName possible_mosi = _form_factor.get(mosi_index); 02126 02127 // Check if the control pair is allowed and skip if it is not 02128 if (!more_restricted.has_pin(possible_clk) && !more_restricted.has_pin(possible_mosi)) { 02129 clk = possible_clk; 02130 mosi = possible_mosi; 02131 break; 02132 } 02133 } 02134 02135 if ((clk == NC) && (mosi == NC)) { 02136 set_control_pins_auto(); 02137 return false; 02138 } 02139 02140 // Find aux pin 02141 int aux_index = 0; 02142 PinName aux = NC; 02143 more_restricted.add(clk); 02144 more_restricted.add(mosi); 02145 for (uint32_t j = 0; j < _form_factor.count(); j++) { 02146 aux_index = j; 02147 const PinName possible_aux = _form_factor.get(aux_index); 02148 02149 // Check if the control pair is allowed and skip if it is not 02150 if (!more_restricted.has_pin(possible_aux)) { 02151 aux = possible_aux; 02152 break; 02153 } 02154 } 02155 if (aux == NC) { 02156 set_control_pins_auto(); 02157 return false; 02158 } 02159 02160 02161 mbed_tester_printf("Testing clk_index=%2i, mosi_index=%2i, miso_index=%2i, aux_index=%2i\r\n", clk_index, mosi_index, miso_index, aux_index); 02162 set_control_pins_manual(clk, mosi, miso, aux); 02163 if (!self_test_control_current()) { 02164 mbed_tester_printf(" Fail\r\n"); 02165 set_control_pins_auto(); 02166 return false; 02167 } 02168 mbed_tester_printf(" Pass\r\n"); 02169 } 02170 set_control_pins_auto(); 02171 return true; 02172 } 02173 02174 bool MbedTester::self_test_control_current() 02175 { 02176 uint8_t buf[4]; 02177 02178 read(TESTER_CONTROL, buf, sizeof(buf)); 02179 02180 return memcmp(buf, "mbed", sizeof(buf)) == 0; 02181 } 02182 02183 bool MbedTester::_find_control_indexes(PhysicalIndex &clk_out, PhysicalIndex &mosi_out, PhysicalIndex &miso_out, PhysicalIndex &aux_out) 02184 { 02185 MbedTesterBitMap<PHYSICAL_PINS> allowed; 02186 const size_t max_pins = _form_factor.count(); 02187 const size_t max_controls = max_pins / 2; 02188 02189 for (size_t i = 0; i < max_pins; i++) { 02190 PinName pin = _form_factor.get(i); 02191 if ((pin == NC) || _exclude_pins.has_pin(pin)) { 02192 // Skip these pins 02193 continue; 02194 } 02195 02196 // Pin is allowed 02197 allowed.set(i); 02198 } 02199 for (size_t i = 0; i < LogicalPinTotal; i++) { 02200 PhysicalIndex index = _mapping[i]; 02201 if (index < PHYSICAL_PINS) { 02202 allowed.clear(index); 02203 } 02204 } 02205 02206 for (size_t i = 0; i < max_controls; i++) { 02207 uint8_t clk_index = i * 2 + 0; 02208 uint8_t mosi_index = i * 2 + 1; 02209 if (!allowed.get(clk_index) || !allowed.get(mosi_index)) { 02210 continue; 02211 } 02212 02213 // Free CLK and MOSI pins found. Mark them as unavailable 02214 allowed.clear(clk_index); 02215 allowed.clear(mosi_index); 02216 mbed::DigitalInOut clk(_form_factor.get(clk_index), PIN_OUTPUT, ::PullNone, 0); 02217 mbed::DigitalInOut mosi(_form_factor.get(mosi_index), PIN_OUTPUT, ::PullNone, 0); 02218 02219 for (uint8_t miso_index = 0; miso_index < max_pins; miso_index++) { 02220 if (!allowed.get(miso_index)) { 02221 continue; 02222 } 02223 02224 mbed::DigitalInOut miso(_form_factor.get(miso_index)); 02225 if (!mbed_tester_test(&clk, &mosi, &miso, miso_index)) { 02226 // Pin doesn't work 02227 continue; 02228 } 02229 02230 // MISO found so find AUX starting from where miso left off 02231 for (uint8_t aux_index = miso_index + 1; aux_index < max_pins; aux_index++) { 02232 if (!allowed.get(aux_index)) { 02233 continue; 02234 } 02235 02236 mbed::DigitalInOut aux(_form_factor.get(aux_index)); 02237 if (!mbed_tester_test(&clk, &mosi, &aux, aux_index)) { 02238 // Pin doesn't work 02239 continue; 02240 } 02241 02242 // Found all 4 pins 02243 clk_out = clk_index; 02244 mosi_out = mosi_index; 02245 miso_out = miso_index; 02246 aux_out = aux_index; 02247 clk.input(); 02248 mosi.input(); 02249 return true; 02250 } 02251 02252 // A valid control channel was found but the system 02253 // does not have enough working pins. 02254 clk.input(); 02255 mosi.input(); 02256 return false; 02257 } 02258 02259 // Set CLK and MOSI pins don't work so set them back to available 02260 clk.input(); 02261 mosi.input(); 02262 allowed.set(clk_index); 02263 allowed.set(mosi_index); 02264 } 02265 return false; 02266 } 02267 02268 void MbedTester::_setup_control_pins() 02269 { 02270 _clk = new mbed::DigitalInOut(_form_factor.get(_clk_index), PIN_OUTPUT, ::PullNone, 0); 02271 _mosi = new mbed::DigitalInOut(_form_factor.get(_mosi_index), PIN_OUTPUT, ::PullNone, 0); 02272 _miso = new mbed::DigitalInOut(_form_factor.get(_miso_index)); 02273 _aux = new mbed::DigitalInOut(_form_factor.get(_aux_index)); 02274 } 02275 02276 void MbedTester::_free_control_pins() 02277 { 02278 if (_clk) { 02279 _clk->input(); 02280 delete _clk; 02281 } 02282 _clk = NULL; 02283 _clk_index = PHYSICAL_NC; 02284 if (_mosi) { 02285 _mosi->input(); 02286 delete _mosi; 02287 } 02288 _mosi = NULL; 02289 _mosi_index = PHYSICAL_NC; 02290 if (_miso) { 02291 _miso->input(); 02292 delete _miso; 02293 } 02294 _miso = NULL; 02295 _miso_index = PHYSICAL_NC; 02296 if (_aux) { 02297 _aux->input(); 02298 delete _aux; 02299 } 02300 _aux = NULL; 02301 _aux_index = PHYSICAL_NC; 02302 _control_valid = false; 02303 } 02304 02305 void MbedTester::_update_control_pins() 02306 { 02307 if (_update_needed()) { 02308 02309 if (!_control_auto) { 02310 error("Invalid control channel configuration"); 02311 } 02312 02313 _free_control_pins(); 02314 if (_find_control_indexes(_clk_index, _mosi_index, _miso_index, _aux_index)) { 02315 mbed_tester_printf("Updating control pins to clk=%i, mosi=%i, miso=%i, aux=%i\r\n", _clk_index, _mosi_index, _miso_index, _aux_index); 02316 _setup_control_pins(); 02317 _control_valid = true; 02318 return; 02319 } else { 02320 error("An MbedTester communication channel could not be created"); 02321 } 02322 } 02323 } 02324 02325 bool MbedTester::_update_needed() 02326 { 02327 if (!_control_valid) { 02328 return true; 02329 } 02330 // Note - mappings beyond the the first two logical banks are allowed to overlap 02331 // with the control channels. These mappings are used for firmware updates and 02332 // IO expander control. 02333 for (size_t i = 0; i < LogicalPinTotal; i++) { 02334 PhysicalIndex pin = _mapping[i]; 02335 if ((pin == _clk_index) || (pin == _mosi_index) || (pin == _miso_index) || (pin == _aux_index)) { 02336 return true; 02337 } 02338 } 02339 return false; 02340 } 02341 02342 void MbedTester::_reset() 02343 { 02344 for (uint32_t i = 0; i < sizeof(_mapping) / sizeof(_mapping[0]); i++) { 02345 _mapping[i] = PHYSICAL_NC; 02346 } 02347 _free_control_pins(); 02348 _control_auto = true; 02349 }
Generated on Tue Jul 12 2022 13:54:34 by
