mirror of https://github.com/ARMmbed/mbed-os.git
923 lines
30 KiB
C++
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
|