mbed-os/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/MbedTester.h

923 lines
30 KiB
C++

/*
* Copyright (c) 2019, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_TESTER_H
#define MBED_TESTER_H
#include "DynamicPinList.h"
#include "platform/FileHandle.h"
#include "platform/Callback.h"
#include "drivers/DigitalInOut.h"
/**
* The base class for controlling the FPGA CI Test Shield
*
* This is the primary interface to the FPGA CI Test Shield. It contains
* all the code to communicate with the FPGA. It also provides high level
* helper functions, such as functions to setup pin multiplexing, to
* select the currently active peripheral and to perform software updates.
*
* Subclasses can inherit from this class and provide further functionality,
* such as the ability to test SPI.
*
* @note Synchronization level: Not protected
*
* Example of how to toggle Arduino pin D6 from the FPGA cI Test Shield:
* @code
* #include "mbed.h"
* #include "MbedTester.h"
*
* const PinList *form_factor = pinmap_ff_default_pins();
* const PinList *restricted = pinmap_restricted_pins();
* MbedTester tester(form_factor, restricted);
*
* int main() {
* // Reset the FPGA CI Test Shield to put it into a known state
* tester.reset();
*
* // Select the GPIO peripheral
* tester.select_peripheral(MbedTester::PeripheralGPIO);
*
* // Map D6 to LogicalPinGPIO0
* tester.pin_map_set(D6, MbedTester::LogicalPinGPIO0);
*
* // Toggle pin D6
* int toggle = 0;
* while (1) {
* tester.gpio_write(MbedTester::LogicalPinGPIO0, toggle, true);
* wait(0.5);
* toggle = !toggle;
* }
* }
* @endcode
*/
class MbedTester {
public:
/*
* This type represents the index of a physical pin on the FPGA.
* This can be any value from 0 to 127. A form factor is used to
* map a PinName to a physical pin index.
*/
typedef uint8_t PhysicalIndex;
/*
* There are 8 logical pins connected to the peripherals inside the FPGA.
* These are logical pins 0 through 7. All peripherals can read from these
* pins and the currently active peripheral can output on these pins.
*
* Each logical pin has a fixed function for a given peripheral which is
* why the same value is defined multiple times. For example logical pin
* 2 is SPI clock (SPISclk) when SPI is the active peripheral and
* UART clear to send (UARTCts) when UART is the active peripheral.
*
* A logic pin can be mapped to any physical pin (PinName type) by calling
* the function MbedTester::pin_map_set.
*/
enum LogicalPin {
LogicalPinGPIO0 = 0,
LogicalPinGPIO1 = 1,
LogicalPinGPIO2 = 2,
LogicalPinGPIO3 = 3,
LogicalPinGPIO4 = 4,
LogicalPinGPIO5 = 5,
LogicalPinGPIO6 = 6,
LogicalPinGPIO7 = 7,
LogicalPinSPIMosi = 0,
LogicalPinSPIMiso = 1,
LogicalPinSPISclk = 2,
LogicalPinSPISsel = 3,
LogicalPinIOMetrics0 = 0,
LogicalPinIOMetrics1 = 1,
LogicalPinIOMetrics2 = 2,
LogicalPinIOMetrics3 = 3,
LogicalPinIOMetrics4 = 4,
LogicalPinIOMetrics5 = 5,
LogicalPinIOMetrics6 = 6,
LogicalPinIOMetrics7 = 7,
LogicalPinUARTTx = 0,
LogicalPinUARTRx = 1,
LogicalPinUARTCts = 2,
LogicalPinUARTRts = 3,
LogicalPinI2CSda = 0,
LogicalPinI2CScl = 1,
LogicalPinCount = 8,
LogicalPinBanks = 2,
LogicalPinTotal = LogicalPinCount * LogicalPinBanks
};
/*
* These are the peripherals internal to the FPGA. A peripheral can be
* selected by calling MbedTester::select_peripheral.
*/
enum Peripheral {
PeripheralGPIO = 1,
PeripheralSPI = 2,
PeripheralUART = 4,
PeripheralI2C = 5,
PeripheralSPISlave = 6
};
/**
* Construct a new MbedTester object
*
* The form factor pins passed into this class must match the
* physical MbedTester shield connected to this board or testing
* will not work correctly. The order of pins in this list must
* match the order of the shield.
*
* The exclude pins list should be used to exclude pins which you either
* don't want to be tested or are not suitable for use as a control
* channel. This list is allowed to contain pins that are not in the
* form factor.
*
* @param form_factor The pins that are available on this form factor
* @param exclude_pins The pins that must not be used
*/
MbedTester(const PinList *form_factor, const PinList *exclude_pins);
/**
* Destroy and cleanup resources associated with this object
*/
~MbedTester();
/**
* Enable automatic selection and update of control pins
*
* Calling this function configures MbedTester to automatically select
* and update the control pins. The control pins are moved if the
* function MbedTester::pin_map_set is called and maps a pin that is being used
* for control.
*
* @note Automatic selection and update of control pins is the default.
* Unless MbedTester::set_control_pins_manual has been called to manually
* set the control pins this function has no effect.
*/
void set_control_pins_auto();
/**
* Set the control pins to use for communication
*
* Manually set the control pins. Calling this function
* disables automatic control pin selection and updates.
* The function MbedTester::pin_map_set must not be used to map over
* control pins when in this mode.
*
* @param clk Clock pin to use as the control channel
* @param mosi Mosi pin to use as the control channel
* @param miso Miso pin to use as the control channel
* @param aux Auxillary pin to use as the control cannel
*/
void set_control_pins_manual(PinName clk, PinName mosi, PinName miso, PinName aux);
/**
* Read FPGA CI Test Shield firmware
*
* Read the firmware on the FPGA CI Test Shield. An optional progress callback
* can be supplied to display progress while the firmware is being read.
*
* @param dest File to write the firmware to. This file must have been opened as writeable
* @param progress Optional progress callback called when the percent complete changes
* @return true if firmware was successfully read, false otherwise
*/
bool firmware_dump(mbed::FileHandle *dest, mbed::Callback<void(uint8_t)> progress = mbed::Callback<void(uint8_t)>());
/**
* Read FPGA CI Test Shield flash
*
* Read the entire flash contents of the FPGA CI Test Shield. An optional progress callback
* can be supplied to display progress while the firmware is being read.
*
* @param dest File to write the firmware to. This file must have been opened as writeable
* @param progress Optional progress callback called when the percent complete changes
* @return true if firmware was successfully read, false otherwise
*/
bool firmware_dump_all(mbed::FileHandle *dest, mbed::Callback<void(uint8_t)> progress = mbed::Callback<void(uint8_t)>());
/**
* Program new FPGA CI Test Shield firmware
*
* Program firmware from the file given. The binary bitstream must be in the correct format
* and contain a correct CRC or the update will fail. To correctly format a bitstream binary
* the post_process_bitstream.py script in the fpga-ci-test-shield repository should be used.
*
* Note - release binaries for the FPGA CI Test Shield have already been formatted and
* can be loaded directly with this function
*
* @param src File containing the new firmware to program
* @param progress Optional progress callback called when the percent complete changes
* @return true if firmware was successfully applied, false otherwise
*/
bool firmware_update(mbed::FileHandle *src, mbed::Callback<void(uint8_t)> progress = mbed::Callback<void(uint8_t)>());
/**
* Map a physical pin to the given logical pin
*
* This function will automatically move the control channel
* pins to avoid interfering with the mapped pin.
*
* @param physical Physical pin on the board
* @param logical Logical pin to map to
*/
void pin_map_set(PinName physical, LogicalPin logical);
/**
* Reset all pin mappings
*
* After this call all pins will be unmapped
*/
void pin_map_reset();
/**
* Reset all peripherals
*
* This does not reset the pin mappings
*/
void peripherals_reset();
/**
* Reset everything
*
* This function resets the state of both the FPGA CI Test Shield
* and the MbedTester object itself.
*
* Reset effects on the FPGA CI Test Shield include:
* - All pins are tristated
* - All pin mappings are reset
* - All pullup/pulldown settings are reset
* - All peripherals are reset
*
* Reset effects on the MbedTester object include
* - Control channels tristated and freed
* - Control channel selection set to automatic
* - Most internal state reinitialized
*/
void reset();
/**
* Reprogram the FPGA
*
* This function causes the FPGA to reboot and reload RAM contents.
* This should be used after MbedTester::firmware_update to load the
* new image.
*/
void reprogram();
/**
* Get the running FPGA firmware version
*
* @return The version of firmware running on the FPGA.
*
*/
uint32_t version();
/**
* Select the currently active peripheral
*
* @param peripheral Active peripheral
*/
void select_peripheral(Peripheral peripheral);
/* **GPIO peripheral functions** */
/**
* Read a gpio pin
*
* @param gpio Logical pin to read from
* @return 1 if the pin is high 0 if the pin is low
*/
int gpio_read(LogicalPin gpio);
/**
* Set value and drive of a gpio pin
*
* @param gpio Logical pin to write to
* @param value 0 to set the pin low or non-zero to set it high
* @param driver 0 to set the pin to Hi-Z or non-zero to drive the pin
*/
void gpio_write(LogicalPin gpio, int value, bool drive);
/* **IO Metrics functions** */
/**
* Start recording metrics on all logical pins
*
* This function resets all past metrics to 0. To
* preserve these call io_metrics_continue instead.
*/
void io_metrics_start();
/**
* Stop recording metrics on all logical pins
*
* This function should be called before any metrics
* are read to ensure the value does not change while
* they are being read.
*/
void io_metrics_stop();
/**
* Continue recording metrics on all logical pins
*
* Resume recording metrics.
*/
void io_metrics_continue();
/**
* Get the shortest low pulse recorded
*
* @param pin Pin to read the metrics for
* @return The shortest number of 100MHz clock cycles the pin was low
*/
uint32_t io_metrics_min_pulse_low(LogicalPin pin);
/**
* Get the shortest high pulse recorded
*
* @param pin Pin to read the metrics for
* @return The shortest number of 100MHz clock cycles the pin was high
*/
uint32_t io_metrics_min_pulse_high(LogicalPin pin);
/**
* Get the longest low pulse recorded
*
* @param pin Pin to read the metrics for
* @return The longest number of 100MHz clock cycles the pin was low
*/
uint32_t io_metrics_max_pulse_low(LogicalPin pin);
/**
* Get the longest high pulse recorded
*
* @param pin Pin to read the metrics for
* @return The longest number of 100MHz clock cycles the pin was high
*/
uint32_t io_metrics_max_pulse_high(LogicalPin pin);
/**
* Get the number of rising edges
*
* @param pin Pin to read the metrics for
* @return The number of rising edges
*/
uint32_t io_metrics_rising_edges(LogicalPin pin);
/**
* Get the number of falling edges
*
* @param pin Pin to read the metrics for
* @return The number of falling edges
*/
uint32_t io_metrics_falling_edges(LogicalPin pin);
/**
* Reset the IO expander modules
*
*/
void pin_pull_reset_all();
/**
* FPGA Pullup mode
*/
enum PullMode {
PullUp,
PullDown,
PullNone
};
/**
* Configure an Mbed pin for a pulldown resistor, pullup resistor, or tristate mode via PinName
*
* @param pin Mbed pin whose mode is being set
* @param mode (MbedTester::PullUp, MbedTester::PullDown, or MbedTester::PullNone)
* @return 0 on success, nonzero on failure
*/
int pin_set_pull(PinName pin, PullMode mode);
/**
* Configure an Mbed pin for a pulldown resistor, pullup resistor, or tristate mode via pin index
*
* @param index Mbed pin index whose mode is being set
* @param mode (MbedTester::PullUp, MbedTester::PullDown, or MbedTester::PullNone)
* @return 0 on success, nonzero on failure
*/
int pin_set_pull_index(int index, PullMode mode);
/*
* Register of the IO expander
*/
enum IOExpanderReg {
RegInput,
RegOutput,
RegConfig
};
/**
* Read a bit for a specific Mbed pin that is set in the input, output, or configuration registers inside of the IO expander via PinName
*
* @param pin Mbed pin whose register bit is being read
* @param reg_type Pin register to access, options are: MbedTester::RegInput, MbedTester::RegOutput, or MbedTester::RegConfig
* @return The value of the bit read
*/
uint8_t io_expander_read(PinName pin, IOExpanderReg reg_type);
/**
* Read a bit for a specific Mbed pin that is set in the input, output, or configuration registers inside of the IO expander via pin index
*
* @param index Mbed pin index whose register bit is being read
* @param reg_type Pin register to access, options are: MbedTester::RegInput, MbedTester::RegOutput, or MbedTester::RegConfig
* @return The value of the bit read
*/
uint8_t io_expander_read_index(int index, IOExpanderReg reg_type);
/**
* Configure an Mbed pin for a pulldown resistor, pullup resistor, or tristate mode
* (this version of the function uses io_expander_i2c_read_bb and io_expander_i2c_write_bb)
*
* @param pin Mbed pin whose mode is being set
* @param mode (MbedTester::PullUp, MbedTester::PullDown, or MbedTester::PullNone)
* @return 0 on success, nonzero on failure
*/
int pin_set_pull_bb(PinName pin, PullMode mode);
/**
* Read a bit for a specific Mbed pin that is set in the input, output, or configuration registers inside of the IO expander
* (this version of the function uses io_expander_i2c_read_bb)
*
* @param pin Mbed pin whose register bit is being read
* @param reg_type Pin register to access, options are: MbedTester::RegInput, MbedTester::RegOutput, or MbedTester::RegConfig
* @return The value of the bit read
*/
uint8_t io_expander_read_bb(PinName pin, IOExpanderReg reg_type);
/**
* Create an analog voltage via the FPGA sys pwm in order to test Mbed AnalogIn
*
* @param enable Enable the FPGA system PWM (false: of, true: on)
* @param voltage The analog voltage that will be created by the FPGA CI test shield (float: 0.0 to 1.0)
*/
void set_analog_out(bool enable, float voltage);
/**
* Turn the FPGA ADC on and off (power management data will be collected while the ADC is on)
*
* @param val FPGA ADC enable bit (false: off, true: on)
*/
void set_sample_adc(bool val);
/**
* Get the result of the analog to digital conversion computed on the FPGA in the form of a voltage reading. The FPGA ADC operates on 0V-1V, which means this function will only ever return a float ranging from 0.0-1.0.
*
* @return The conversion result in the form of a voltage measurement for AnalogMuxIn, Eg. a return value of 0.7 means the ADC on the FPGA read 0.7 volts on its analog input
*/
float get_analog_in();
/**
* Similar to 'get_analog_in' but returns a voltage reading from ANIN0-3
*
* @param index ANIN pin to read (0-3)
* @return The conversion result in the form of a voltage measurement for ANIN0-3
*/
float get_anin_voltage(int index);
/* **Mid level system access** */
/*
* These are the pins on the FPGA that are not connected to the Mbed board.
* These can be controlled by using MbedTester::sys_pin_read and MbedTester::sys_pin_write.
* These should not be used directly when using the FPGA CI Test Shield. The higher layer
* APIs should be used instead.
*/
enum SystemPin {
Reset,
Reprogram,
DigitalID0,
DigitalID1,
DigitalID2,
Led0,
Led1,
Led2,
Led3,
SPIIO0,
SPIIO1,
SPIIO2,
SPIIO3,
SPIClk,
SPICS,
I2CReset,
I2CSda0,
I2CSda1,
I2CSda2,
I2CScl0,
I2CScl1,
I2CScl2,
AnalogMuxEnable,
AnalogMuxPwmOut,
AnalogMuxIn,
AnalogMuxAddr0,
AnalogMuxAddr1,
AnalogMuxAddr2,
AnalogMuxAddr3,
AnalogMuxAddr4,
AnalogMuxAddr5,
AnalogMuxAddr6,
AnalogMuxAddr7,
AnalogInP0,
AnalogInP1,
AnalogInP2,
AnalogInP3,
AnalogInN0,
AnalogInN1,
AnalogInN2,
AnalogInN3,
SystemPinCount
};
/**
* Read from the given system pin
*
* @param pin The pin to read from
* @return true if 1 was read, false if 0
*/
bool sys_pin_read(SystemPin pin);
/**
* Write to the given system pin
*
* @param pin The pin to write to
* @param value The value to output on the pin when driven
* @param true to drive the output, false to set the output high-z
* @return true if 1 was read, false if 0
*/
void sys_pin_write(SystemPin pin, int value, bool drive);
/**
* I2C read on I2C system channels 0, 1, or 2
*
* @param i2c_index The number corresponding to the system i2c bus being used (0, 1, or 2)
* @param dev_addr The I2C address of the device being read from
* @param start_reg The internal device address where the read will start
* @param data Data buffer for data to be read into
* @param length The number of bytes to read
* @return 0 on success (ACK), nonzero on failure (NACK)
*/
int io_expander_i2c_read(uint8_t i2c_index, uint8_t dev_addr, uint8_t start_reg, uint8_t *data, int length);
/**
* I2C write on I2C system channels 0, 1, or 2
*
* @param i2c_index The number corresponding to the system i2c bus being used (0, 1, or 2)
* @param dev_addr The I2C address of the device being written to
* @param data The data to be written
* @param length The number of bytes to be written
* @return 0 on success (ACK), nonzero on failure (NACK)
*/
int io_expander_i2c_write(uint8_t i2c_index, uint8_t dev_addr, uint8_t *data, int length);
/**
* I2C read on I2C system channels 0, 1, or 2
* (bit banged version of function, bit banged over control channel)
*
* @param sda System pin used for sda
* @param scl System pin used for scl
* @param dev_addr The I2C address of the device being read from
* @param start_reg The internal device address where the read will start
* @param data Data buffer for data to be read into
* @param length The number of bytes to read
* @return 0 on success (ACK), nonzero on failure (NACK)
*/
int io_expander_i2c_read_bb(SystemPin sda, SystemPin scl, uint8_t dev_addr, uint8_t start_reg, uint8_t *data, int length);
/**
* I2C write on I2C system channels 0, 1, or 2
* (bit banged version of function, bit banged over control channel)
*
* @param sda System pin used for sda
* @param scl System pin used for scl
* @param dev_addr The I2C address of the device being written to
* @param data The data to be written
* @param length The number of bytes to be written
* @return 0 on success (ACK), nonzero on failure (NACK)
*/
int io_expander_i2c_write_bb(SystemPin sda, SystemPin scl, uint8_t dev_addr, uint8_t *data, int length);
/**
* Set the AnalogMuxAddr pins on the FPGA via PinName
*
* @param pin The Mbed pin that the analog signal will be routed to
* @return 0 on success, nonzero on failure
*/
int set_mux_addr(PinName pin);
/**
* Set the AnalogMuxAddr pins on the FPGA via pin index
*
* @param index The Mbed pin index that the analog signal will be routed to
* @return 0 on success, nonzero on failure
*/
int set_mux_addr_index(int index);
/* **AnalogIn peripheral functions** */
/**
* Turn on/off the analog muxes
*
* @param val false: off, true: on
*/
void set_mux_enable(bool val);
/**
* Turn on/off pwm output on FPGA to test Mbed AnalogIn
*
* @param val false: off, true: on
*/
void set_pwm_enable(bool val);
/**
* Check if FPGA pwm out is on or off
*
* @return FPGA enable bit (false: off, true: on)
*/
bool get_pwm_enable();
/**
* Set the pwm output period and number of cycles high (duty cycle) on the FPGA
*
* @param period In units of clk cycles
* @param cycles_high In units of clk cycles
*/
void set_pwm_period_and_cycles_high(uint32_t period, uint32_t cycles_high);
/**
* Get the pwm output period of the FPGA
*
* @return FPGA pwm output period in units of clk cycles
*/
uint32_t get_pwm_period();
/**
* Get the number of cycles that are high (duty cycle) from FPGA pwm
*
* @return FPGA pwm output cycles high
*/
uint8_t get_pwm_cycles_high();
/**
* Get the 12-bit analog to digital conversion result from the FPGA
*
* @return 12-bit FPGA ADC result for AnalogMuxIn
*/
uint16_t get_analogmuxin_measurement();
/**
* Similar to 'get_analogmuxin_measurement' but returns the current XADC measurement for ANIN0-3
*
* @param index ANIN pin to read (0-3)
* @return 12-bit FPGA ADC result for ANIN0-3
*/
uint16_t get_anin_measurement(int index);
/**
* Gets (by reference) the sum of all ANIN ADC results for any of the 4 ANIN pins specified by the index,
* number of ADC sample sequences that have completed since the XADC was turned on, and the number of FPGA clk cycles
* that have taken place since the ADC was turned on.
*
* @param index ANIN pin of which to get sum of results (0-3)
* @param sum The sum of all specified ANIN pin's ADC results
* @param samples The number of ADC sample sequences that have completed since the XADC was turned on
* @param cycles The number of FPGA clk cycles that have taken place since the ADC was turned on
*/
void get_anin_sum_samples_cycles(int index, uint64_t *sum, uint32_t *samples, uint64_t *cycles);
/**
* Allows safe reading of FPGA ADC related values while the FPGA ADC is on
* If snapshot is set then the ADC values will be safely latched in the FPGA and safe to read.
* The RTL will set snapshot to 0 after 1 clk cycle.
*/
void set_snapshot();
/**
* Set the current system pin mode to disabled
*
* This releases any pin mappings that were set by the previous pin mode.
*/
void sys_pin_mode_disabled();
/**
* Set the current system pin mode to serial flash
*
* Remap physical pins to the serial flash the FPGA boots from.
* This is used for firmware updates.
*
* @param mosi The physical pin index to connect to serial flash mosi
* @param miso The physical pin index to connect to serial flash miso
* @param clk The physical pin index to connect to serial flash clk
* @param ssel The physical pin index to connect to serial flash cs
*/
void sys_pin_mode_spi_serial_flash(PhysicalIndex mosi, PhysicalIndex miso, PhysicalIndex clk, PhysicalIndex ssel);
/**
* Set the current system pin mode to io expander I2C bus
*
* Remap physical pins to the io expander I2C bus. The IO expanders
* are used for setting pullups and pulldowns.
*
* @param index The index of the I2C bus to connect to
* @param sda_in Physical pin index for the FPGA to output the state of SDA on
* @param sda_val Physical pin index for the FPGA to read SDA from. When in this mode the Mbed board
* must always drive this pin. Driving a 0 causes the FPGA to pull the SDA on the I2C bus low. Setting
* a 1 causes the FPGA to let SDA on the I2C bus float (and get pulled to 1).
* @param scl_in Physical pin index for the FPGA to output the state of SCL on
* @param scl_val Physical pin index for the FPGA to read SCL from. When in this mode the Mbed board
* must always drive this pin. Driving a 0 causes the FPGA to pull the SCL on the I2C bus low. Setting
* a 1 causes the FPGA to let SDA on the SCL bus float (and get pulled to 1).
*/
void sys_pin_mode_i2c_io_expander(int index, PhysicalIndex sda_in, PhysicalIndex sda_val, PhysicalIndex scl_in, PhysicalIndex scl_val);
/**
* Map a physical pin index to the given logical pin
*
* This function will automatically move the control channel
* pins to avoid interfering with the mapped pin. The physical
* pin index does not need to be part of the form factor.
*
* @param physical_index Index of the physical pin on the board
* @param logical Logical pin to map to
*/
void pin_map_index(PhysicalIndex physical_index, LogicalPin logical);
/* **Low level memory access** */
/**
* Write to tester memory
*
* @addr addr Address to write to
* @param data Data to write
* @param size Number of bytes to write
*/
void write(uint32_t addr, const uint8_t *data, uint32_t size);
/**
* Read from tester memory
*
* @addr addr Address to read from
* @param data Buffer to fill with data
* @param size Number of bytes to read
*/
void read(uint32_t addr, uint8_t *data, uint32_t size);
/* **Self tests** */
/**
* Run all self tests
*
* @return true if all self tests pass, false otherwise
*/
bool self_test_all();
/**
* Test that all allowed control channels can be used
*
* Check that all pairs of clk and mosi which aren't in
* the restricted list can be used.
*
* @note CLK and MOSI lines are paired, where CLK is always
* on an even index and MOSI is always on an oddd index:
* clk_index_N = N * 2
* mosi_index_N = N * 2 + 1
*
* @note This functions sets the control pin management mode
* to automatic when it completes.
*
* @return true if all control channel pairs (clk and mosi) of this
* configuration can be used, false otherwise
*/
bool self_test_control_channels();
/**
* Test that all allowed control miso lines can be used
*
* Check that every pin of this form factor aside from the
* pins in the restricted list can be used as miso.
*
* @note This functions sets the control pin management mode
* to automatic when it completes.
*
* @return true if all control channel miso lines of this
* configuration can be used, false otherwise
*/
bool self_test_control_miso();
/**
* Test that the current control channel works
*
* @return true if communication is successful, false otherwise
*/
bool self_test_control_current();
private:
/*
* Find suitable control pins
*
* This function finds the appropriate set of pins and test to ensure that communication with
* the FPGA can be performed over them. Before calling this function MbedTester pins must be
* freed by calling MbedTester::_free_control_pins.
*
* @param clk_out Clock pin to find and set
* @param mosi_out Mosi pin to find and set
* @param miso_out Miso pin to find and set
* @param aux_out Aux pin to find and set
* @return true if all pins were found, false otherwise
*/
bool _find_control_indexes(PhysicalIndex &clk_out, PhysicalIndex &mosi_out, PhysicalIndex &miso_out, PhysicalIndex &aux_out);
/*
* Allocate control pins
*
* The pin indexes must already have been found
*/
void _setup_control_pins();
/*
* Free control pins
*
* This function is safe to call even if the pins have been freed
*/
void _free_control_pins();
/*
* Update the control channel if needed
*
* Open a control channel using allowed pins:
* - Pin must be in the form factor
* - Pin must not be in the exclude list
* - Pin must not be mapped already
*/
void _update_control_pins();
/*
* Check if this control channel needs to be updated
*
* @return true if the control channel needs to be updated, false otherwise
*/
bool _update_needed();
/*
* Reset the state of the MbedTester class
*
* This does not effect the state of the FPGA in any way.
*/
void _reset();
PhysicalIndex _mapping[LogicalPinCount * (LogicalPinBanks + 1)];
DynamicPinList _form_factor;
DynamicPinList _exclude_pins;
bool _control_auto;
bool _control_valid;
PhysicalIndex _clk_index;
PhysicalIndex _mosi_index;
PhysicalIndex _miso_index;
PhysicalIndex _aux_index;
mbed::DigitalInOut *_clk;
mbed::DigitalInOut *_mosi;
mbed::DigitalInOut *_miso;
mbed::DigitalInOut *_aux;
/*
* Used to reset IO expander chips only once the first time
* any IO expander is accessed as well as during an io_exp_test
*/
int _init_io_exp_rst_flag;
};
#endif