Merge pull request #10540 from c1728p9/fpga_ci_test_shield

Check in files for the FPGA CI Test Shield
pull/10663/head
Martin Kojtal 2019-05-24 12:56:35 +01:00 committed by GitHub
commit a4738fa9a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 5374 additions and 0 deletions

View File

@ -0,0 +1,75 @@
/*
* 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.
*/
#include "DynamicPinList.h"
DynamicPinList::DynamicPinList()
{
}
DynamicPinList::DynamicPinList(const PinList *pin_list)
{
for (uint32_t i = 0; i < pin_list->count; i++) {
_pins.push_back(pin_list->pins[i]);
}
}
DynamicPinList::DynamicPinList(const DynamicPinList &other)
{
_pins = other._pins;
}
void DynamicPinList::add(PinName pin)
{
_pins.push_back(pin);
}
bool DynamicPinList::has_pin(PinName pin) const
{
for (uint32_t i = 0; i < _pins.size(); i++) {
if (pin == _pins[i]) {
return true;
}
}
return false;
}
void DynamicPinList::clear()
{
_pins.clear();
}
uint32_t DynamicPinList::count() const
{
return _pins.size();
}
PinName DynamicPinList::get(uint32_t index) const
{
return index < _pins.size() ? _pins[index] : NC;
}
int DynamicPinList::index(PinName pin) const
{
for (uint32_t i = 0; i < _pins.size(); i++) {
if (pin == _pins[i]) {
return i;
}
}
return -1;
}

View File

@ -0,0 +1,92 @@
/*
* 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 DYNAMIC_PIN_LIST_H
#define DYNAMIC_PIN_LIST_H
#include "pinmap.h"
#include <vector>
class DynamicPinList {
public:
/**
* Create an empty pin list
*/
DynamicPinList();
/**
* Create a pin list with the given contents
*
* @param pin_list List of pins to create this list from
*/
DynamicPinList(const PinList *pin_list);
/**
* Create a copy of another list
*
* @param other Other object to copy contruct this from
*/
DynamicPinList(const DynamicPinList &other);
/**
* Add a pin to the pin list
*
* @param pin Pin to add to this pin list
*/
void add(PinName pin);
/**
* Check if the given pin is in this list
*
* @param pin Pin to check for in the list
* @return true if the pin is in the list, false otherwise
*/
bool has_pin(PinName pin) const;
/**
* Empty this pin list
*/
void clear();
/**
* Return the number of pins in this list
*
* @return Elements in this list
*/
uint32_t count() const;
/**
* Get the pin at the given index
*
* @return Pin at this position
*/
PinName get(uint32_t index) const;
/**
* Get the location of the given pin
*
* @param pin Pin to get the index of
* @return pin index or -1 if pin is not in the list
*/
int index(PinName pin) const;
private:
std::vector<PinName> _pins;
};
#endif

View File

@ -0,0 +1,144 @@
/*
* 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.
*/
#include "I2CTester.h"
#include "fpga_config.h"
uint8_t I2CTester::num_starts()
{
uint8_t num_starts = 0;
read(TESTER_I2C_STARTS, &num_starts, sizeof(num_starts));
return num_starts;
}
uint8_t I2CTester::num_stops()
{
uint8_t num_stops = 0;
read(TESTER_I2C_STOPS, &num_stops, sizeof(num_stops));
return num_stops;
}
uint16_t I2CTester::num_acks()
{
uint16_t num_acks = 0;
read(TESTER_I2C_ACKS, (uint8_t *)&num_acks, sizeof(num_acks));
return num_acks;
}
uint16_t I2CTester::num_nacks()
{
uint16_t num_nacks = 0;
read(TESTER_I2C_NACKS, (uint8_t *)&num_nacks, sizeof(num_nacks));
return num_nacks;
}
uint16_t I2CTester::transfer_count()
{
uint16_t transfers = 0;
MBED_ASSERT(sizeof(transfers) == TESTER_I2C_TRANSFERS_SIZE);
read(TESTER_I2C_TRANSFERS, (uint8_t *)&transfers, sizeof(transfers));
return transfers;
}
uint32_t I2CTester::get_receive_checksum()
{
uint32_t to_slave_checksum = 0;
MBED_ASSERT(sizeof(to_slave_checksum) == TESTER_I2C_TO_SLAVE_CHECKSUM_SIZE);
read(TESTER_I2C_TO_SLAVE_CHECKSUM, (uint8_t *)&to_slave_checksum, sizeof(to_slave_checksum));
return to_slave_checksum;
}
uint8_t I2CTester::state_num()
{
uint8_t state_num = 0;
read(TESTER_I2C_STATE_NUM, &state_num, sizeof(state_num));
return state_num;
}
uint8_t I2CTester::num_dev_addr_matches()
{
uint8_t num_correct = 0;
read(TESTER_I2C_NUMBER_DEV_ADDR_MATCHES, &num_correct, sizeof(num_correct));
return num_correct;
}
void I2CTester::set_device_address(uint16_t addr)
{
uint16_t data = addr;
write(TESTER_I2C_DEVICE_ADDRESS, (uint8_t *)&data, sizeof(data));
}
uint16_t I2CTester::get_device_address()
{
uint16_t addr = 0;
read(TESTER_I2C_DEVICE_ADDRESS, (uint8_t *)&addr, sizeof(addr));
return addr;
}
void I2CTester::set_sda(uint8_t value)
{
uint8_t val = value;
write(TESTER_I2C_SET_SDA, &val, sizeof(val));
}
uint8_t I2CTester::get_prev_to_slave_4()
{
uint8_t prev_to_slave_4 = 0;
read(TESTER_I2C_PREV_TO_SLAVE_4, &prev_to_slave_4, sizeof(prev_to_slave_4));
return prev_to_slave_4;
}
uint8_t I2CTester::get_prev_to_slave_3()
{
uint8_t prev_to_slave_3 = 0;
read(TESTER_I2C_PREV_TO_SLAVE_3, &prev_to_slave_3, sizeof(prev_to_slave_3));
return prev_to_slave_3;
}
uint8_t I2CTester::get_prev_to_slave_2()
{
uint8_t prev_to_slave_2 = 0;
read(TESTER_I2C_PREV_TO_SLAVE_2, &prev_to_slave_2, sizeof(prev_to_slave_2));
return prev_to_slave_2;
}
uint8_t I2CTester::get_prev_to_slave_1()
{
uint8_t prev_to_slave_1 = 0;
read(TESTER_I2C_PREV_TO_SLAVE_1, &prev_to_slave_1, sizeof(prev_to_slave_1));
return prev_to_slave_1;
}
void I2CTester::set_next_from_slave(uint8_t value)
{
uint8_t val = value;
write(TESTER_I2C_NEXT_FROM_SLAVE, &val, sizeof(val));
}
uint8_t I2CTester::get_next_from_slave()
{
uint8_t next_from_slave = 0;
read(TESTER_I2C_NEXT_FROM_SLAVE, &next_from_slave, sizeof(next_from_slave));
return next_from_slave;
}
uint16_t I2CTester::num_writes()
{
uint16_t num_writes = 0;
read(TESTER_I2C_NUM_WRITES, (uint8_t *)&num_writes, sizeof(num_writes));
return num_writes;
}
uint16_t I2CTester::num_reads()
{
uint16_t num_reads = 0;
read(TESTER_I2C_NUM_READS, (uint8_t *)&num_reads, sizeof(num_reads));
return num_reads;
}

View File

@ -0,0 +1,173 @@
/*
* 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 I2C_TESTER_H
#define I2C_TESTER_H
#include "MbedTester.h"
class I2CTester: public MbedTester {
public:
I2CTester(const PinList *form_factor, const PinList *exclude_pins)
: MbedTester(form_factor, exclude_pins)
{
}
/* **I2C peripheral functions** */
/**
* Get the number of start conditions since last I2C reset
*
* @return The number of start conditions
*/
uint8_t num_starts();
/**
* Get the number of stop conditions since last I2C reset
*
* @return The number of stop conditions
*/
uint8_t num_stops();
/**
* Get the number of ACKs since last I2C reset
*
* @return The number of ACKs
*/
uint16_t num_acks();
/**
* Get the number of NACKs since last I2C reset
*
* @return The number of NACKs
*/
uint16_t num_nacks();
/**
* Read the number of transfers which have occurred, not including the device address byte
*
* @return The number of I2C transfers that have completed since
* i2c was reset, not including the device address byte
*/
uint16_t transfer_count();
/**
* Read a checksum of data send to the tester
*
* @return The sum of all bytes sent to the tester since reset
*/
uint32_t get_receive_checksum();
/**
* Get the I2C slave state number
*
* @return The state number
*/
uint8_t state_num();
/**
* Get the number of times the device address has been sent correctly
*
* @return The number of times the device address has been sent correctly
*/
uint8_t num_dev_addr_matches();
/**
* Set the I2C slave device address
*
* @param addr New address for slave device
*/
void set_device_address(uint16_t addr);
/**
* Get the I2C slave device address
*
* @return The slave device address
*/
uint16_t get_device_address();
/**
* Set SDA (test mode)
*
* @param value Test value for SDA
*/
void set_sda(uint8_t value);
/**
* Get the value written to slave in the fourth to last transaction
*
* @return value written to slave in the fourth to last transaction
*/
uint8_t get_prev_to_slave_4();
/**
* Get the value written to slave in the third to last transaction
*
* @return value written to slave in the third to last transaction
*/
uint8_t get_prev_to_slave_3();
/**
* Get the value written to slave in the second to last transaction
*
* @return value written to slave in the second to last transaction
*/
uint8_t get_prev_to_slave_2();
/**
* Get the value written to slave in the last transaction
*
* @return value written to slave in the last transaction
*/
uint8_t get_prev_to_slave_1();
/**
* Set the value to be read from slave in next read transaction
*
* @param value Value to be read from slave in next read transaction
*/
void set_next_from_slave(uint8_t value);
/**
* Get the value to be read from slave in next read transaction
*
* @return Value to be read from slave in next read transaction
*/
uint8_t get_next_from_slave();
/**
* Read the number of writes which have occurred, not including the device address byte
*
* @return The number of I2C writes that have completed since
* i2c was reset, not including the device address byte
*/
uint16_t num_writes();
/**
* Read the number of reads which have occurred
*
* @return The number of I2C reads that have completed since
* i2c was reset
*/
uint16_t num_reads();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,922 @@
/*
* 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 the LED
* 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

View File

@ -0,0 +1,70 @@
/*
* 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.
*/
#include "SPIMasterTester.h"
#include "fpga_config.h"
uint16_t SPIMasterTester::get_transfer_count()
{
return SPITester::get_transfer_count(TESTER_SPI_MASTER_TRANSFERS, TESTER_SPI_MASTER_TRANSFERS_SIZE);
}
uint32_t SPIMasterTester::get_receive_checksum()
{
return SPITester::get_receive_checksum(TESTER_SPI_MASTER_TO_SLAVE_CHECKSUM, TESTER_SPI_MASTER_TO_SLAVE_CHECKSUM_SIZE);
}
void SPIMasterTester::set_mode(SPITester::SpiMode mode)
{
SPITester::set_mode(mode, TESTER_SPI_MASTER_CTRL, TESTER_SPI_MASTER_CTRL_SIZE, TESTER_SPI_MASTER_CLK_MODE_OFFSET, TESTER_SPI_MASTER_CLK_MODE_SIZE);
}
void SPIMasterTester::set_bit_order(SPITester::SpiBitOrder bit_order)
{
SPITester::set_bit_order(bit_order, TESTER_SPI_MASTER_CTRL, TESTER_SPI_MASTER_CTRL_SIZE, TESTER_SPI_MASTER_BIT_ORDER_OFFSET, TESTER_SPI_MASTER_BIT_ORDER_SIZE);
}
void SPIMasterTester::set_sym_size(uint32_t sym_size)
{
SPITester::set_sym_size(sym_size, TESTER_SPI_MASTER_CTRL, TESTER_SPI_MASTER_CTRL_SIZE, TESTER_SPI_MASTER_SYM_SIZE_OFFSET, TESTER_SPI_MASTER_SYM_SIZE_SIZE);
}
void SPIMasterTester::set_duplex_mode(SPITester::SpiDuplex duplex)
{
SPITester::set_duplex_mode(duplex, TESTER_SPI_MASTER_CTRL, TESTER_SPI_MASTER_CTRL_SIZE, TESTER_SPI_MASTER_DUPLEX_OFFSET, TESTER_SPI_MASTER_DUPLEX_SIZE);
}
void SPIMasterTester::set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt)
{
SPITester::set_hd_tx_rx_cnt(tx_cnt, rx_cnt, TESTER_SPI_MASTER_HD_RX_CNT, TESTER_SPI_MASTER_HD_RX_CNT_SIZE, TESTER_SPI_MASTER_HD_TX_CNT, TESTER_SPI_MASTER_HD_TX_CNT_SIZE);
}
uint32_t SPIMasterTester::get_cs_to_first_clk_edge_ns()
{
uint32_t delay_ns;
read(TESTER_SPI_MASTER_CS_TO_FIRST_SCLK_CNT, (uint8_t *)&delay_ns, TESTER_SPI_MASTER_CS_TO_FIRST_SCLK_CNT_SIZE);
return (delay_ns * 10);
}
uint32_t SPIMasterTester::get_last_clk_edge_to_cs_ns()
{
uint32_t delay_ns;
read(TESTER_SPI_MASTER_LAST_SCLK_TO_CS_CNT, (uint8_t *)&delay_ns, TESTER_SPI_MASTER_LAST_SCLK_TO_CS_CNT_SIZE);
return (delay_ns * 10);
}

View File

@ -0,0 +1,109 @@
/*
* 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 SPI_MASTER_TESTER_H
#define SPI_MASTER_TESTER_H
#include "SPITester.h"
class SPIMasterTester: public SPITester {
public:
SPIMasterTester(const PinList *form_factor, const PinList *exclude_pins)
: SPITester(form_factor, exclude_pins)
{
}
/**
* Read the number of transfers which have occurred
*
* @return The number of SPI transfers that have completed since
* spi was reset.
*/
uint16_t get_transfer_count();
/**
* Read a checksum of data send to the tester
*
* @return The sum of all bytes sent to the tester since reset.
*/
uint32_t get_receive_checksum();
/**
* Set the clock mode of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_mode(SpiMode mode);
/**
* Set bit order durring transmission of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_bit_order(SpiBitOrder bit_order);
/**
* Set symbol size used durring transmission of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_sym_size(uint32_t sym_size);
/**
* Set full-duplex/half-duplex transmission mode of the spi_slave module.
*
* @param duplex duplex mode used for the transmission
*/
void set_duplex_mode(SpiDuplex duplex);
/**
* Set tx/rx symbol count.
*
* @tx_cnt TX symbol count
* @rx_cnt RX symbol count
*
* @note Required only in Half-Duplex mode.
*/
void set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt);
/**
* Get nano seconds between chip select assertion and the first spi clock edge.
*
* @return nano seconds between chip select assertion and the first spi clock edge.
*
* @note Number of nano seconds is calculated based of number of counted clk changes and
* clk frequency (100 MHz => 1 clk tick corresponds to 10 ns).
* Accuracy of the returned value is +/- 10 ns.
*/
uint32_t get_cs_to_first_clk_edge_ns();
/**
* Get nano seconds between last spi clock edge and chip select de-assertion.
*
* @return nano seconds between last spi clock edge and chip select de-assertion.
*
* @note Number of nano seconds is calculated based of number of counted clk changes and
* clk frequency (100 MHz => 1 clk tick corresponds to 10 ns).
* Accuracy of the returned value is +/- 10 ns.
*/
uint32_t get_last_clk_edge_to_cs_ns();
};
#endif

View File

@ -0,0 +1,84 @@
/*
* 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.
*/
#include "SPISlaveTester.h"
#include "fpga_config.h"
uint16_t SPISlaveTester::get_transfer_count()
{
return SPITester::get_transfer_count(TESTER_SPI_SLAVE_TRANSFERS, TESTER_SPI_SLAVE_TRANSFERS_SIZE);
}
uint32_t SPISlaveTester::get_receive_checksum()
{
return SPITester::get_receive_checksum(TESTER_SPI_SLAVE_TO_MASTER_CHECKSUM, TESTER_SPI_SLAVE_TO_MASTER_CHECKSUM_SIZE);
}
void SPISlaveTester::set_mode(SPITester::SpiMode mode)
{
SPITester::set_mode(mode, TESTER_SPI_SLAVE_CTRL, TESTER_SPI_SLAVE_CTRL_SIZE, TESTER_SPI_SLAVE_CLK_MODE_OFFSET, TESTER_SPI_SLAVE_CLK_MODE_SIZE);
}
void SPISlaveTester::set_bit_order(SPITester::SpiBitOrder bit_order)
{
SPITester::set_bit_order(bit_order, TESTER_SPI_SLAVE_CTRL, TESTER_SPI_SLAVE_CTRL_SIZE, TESTER_SPI_SLAVE_BIT_ORDER_OFFSET, TESTER_SPI_SLAVE_BIT_ORDER_SIZE);
}
void SPISlaveTester::set_sym_size(uint32_t sym_size)
{
SPITester::set_sym_size(sym_size, TESTER_SPI_SLAVE_CTRL, TESTER_SPI_SLAVE_CTRL_SIZE, TESTER_SPI_SLAVE_SYM_SIZE_OFFSET, TESTER_SPI_SLAVE_SYM_SIZE_SIZE);
}
void SPISlaveTester::set_duplex_mode(SPITester::SpiDuplex duplex)
{
SPITester::set_duplex_mode(duplex, TESTER_SPI_SLAVE_CTRL, TESTER_SPI_SLAVE_CTRL_SIZE, TESTER_SPI_SLAVE_DUPLEX_OFFSET, TESTER_SPI_SLAVE_DUPLEX_SIZE);
}
void SPISlaveTester::set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt)
{
SPITester::set_hd_tx_rx_cnt(tx_cnt, rx_cnt, TESTER_SPI_SLAVE_HD_RX_CNT, TESTER_SPI_SLAVE_HD_RX_CNT_SIZE, TESTER_SPI_SLAVE_HD_TX_CNT, TESTER_SPI_SLAVE_HD_TX_CNT_SIZE);
}
void SPISlaveTester::set_spi_master_freq(uint16_t clk_div)
{
write(TESTER_SPI_SLAVE_CLK_DIV, (uint8_t *)&clk_div, TESTER_SPI_SLAVE_CLK_DIV_SIZE);
}
void SPISlaveTester::set_num_of_symbols(uint16_t num_of_sym)
{
write(TESTER_SPI_SLAVE_NUM_OF_SYMBOLS, (uint8_t *)&num_of_sym, TESTER_SPI_SLAVE_NUM_OF_SYMBOLS_SIZE);
}
void SPISlaveTester::set_start_delay_us(uint8_t start_delay_us)
{
write(TESTER_SPI_SLAVE_START_DELAY_US, (uint8_t *)&start_delay_us, TESTER_SPI_SLAVE_START_DELAY_US_SIZE);
}
void SPISlaveTester::set_sym_delay_ns(uint16_t sym_delay_ns)
{
const uint16_t sym_delay_ticks = (sym_delay_ns + 9) / 10; // round up
write(TESTER_SPI_SLAVE_SYM_DELAY_TICKS, (uint8_t *)&sym_delay_ticks, TESTER_SPI_SLAVE_SYM_DELAY_TICKS_SIZE);
}
void SPISlaveTester::start_transfer()
{
uint32_t spi_ctrl = 0;
read(TESTER_SPI_SLAVE_CTRL, (uint8_t *)&spi_ctrl, TESTER_SPI_SLAVE_CTRL_SIZE);
spi_ctrl &= ~(((1 << TESTER_SPI_SLAVE_START_REQUEST_SIZE) - 1) << TESTER_SPI_SLAVE_START_REQUEST_OFFSET);
spi_ctrl |= (1 << TESTER_SPI_SLAVE_START_REQUEST_OFFSET);
write(TESTER_SPI_SLAVE_CTRL, (uint8_t *)&spi_ctrl, TESTER_SPI_SLAVE_CTRL_SIZE);
}

View File

@ -0,0 +1,121 @@
/*
* 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 SPI_SLAVE_TESTER_H
#define SPI_SLAVE_TESTER_H
#include "SPITester.h"
class SPISlaveTester: public SPITester {
public:
SPISlaveTester(const PinList *form_factor, const PinList *exclude_pins)
: SPITester(form_factor, exclude_pins)
{
}
/**
* Read the number of transfers which have occurred
*
* @return The number of SPI transfers that have completed since
* spi was reset.
*/
uint16_t get_transfer_count();
/**
* Read a checksum of data sent to the tester
*
* @return The sum of all bytes sent to the tester since reset.
*/
uint32_t get_receive_checksum();
/**
* Set the clock mode of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_mode(SpiMode mode);
/**
* Set bit order during transmission of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_bit_order(SpiBitOrder bit_order);
/**
* Set symbol size used during transmission of the spi_slave module.
*
* @param mode Spi clock mode
*/
void set_sym_size(uint32_t sym_size);
/**
* Set full-duplex/half-duplex transmission mode of the spi_slave module.
*
* @param duplex duplex mode used for the transmission
*/
void set_duplex_mode(SpiDuplex duplex);
/**
* Set tx/rx symbol count.
*
* @tx_cnt TX symbol count
* @rx_cnt RX symbol count
*
* @note Required only in Half-Duplex mode.
*/
void set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt);
/**
* Set divisor to generate spi clock from FPGA base clock (100 MHz).
*
* @clk_div clock divisor.
*/
void set_spi_master_freq(uint16_t clk_div);
/**
* Set number of symbols to be transmitted by spi master.
*
* @num_of_sym Number of symbols to be transmitted by spi master.
*/
void set_num_of_symbols(uint16_t num_of_sym);
/**
* Set delay in us between start request and start of transmission.
*
* @start_delay_us Delay in us between start request and start of transmission.
*/
void set_start_delay_us(uint8_t start_delay_us);
/**
* Set delay in ns between transmission of successive symbols.
*
* @sym_delay_ns Delay in ns between transmission of successive symbols.
*/
void set_sym_delay_ns(uint16_t sym_delay_ns);
/**
* Request transmission start from FPGA master.
*
* @note Transmission will be started after the specified delay.
*/
void start_transfer();
};
#endif

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
#include "SPITester.h"
#include "fpga_config.h"
uint16_t SPITester::get_transfer_count(uint32_t addr_transfers, uint32_t size_transfers)
{
uint16_t transfers = 0;
MBED_ASSERT(sizeof(transfers) == size_transfers);
read(addr_transfers, (uint8_t *)&transfers, sizeof(transfers));
return transfers;
}
uint32_t SPITester::get_receive_checksum(uint32_t addr_checksum, uint32_t size_checksum)
{
uint32_t checksum = 0;
MBED_ASSERT(sizeof(checksum) == size_checksum);
read(addr_checksum, (uint8_t *)&checksum, sizeof(checksum));
return checksum;
}
void SPITester::set_mode(SPITester::SpiMode mode, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_clk_mode, uint32_t size_clk_mode)
{
uint32_t spi_ctrl = 0;
read(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
spi_ctrl &= ~(((1 << size_clk_mode) - 1) << offset_clk_mode);
spi_ctrl |= (mode << offset_clk_mode);
write(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
}
void SPITester::set_bit_order(SPITester::SpiBitOrder bit_order, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_bit_order, uint32_t size_bit_order)
{
uint32_t spi_ctrl = 0;
read(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
spi_ctrl &= ~(((1 << size_bit_order) - 1) << offset_bit_order);
spi_ctrl |= (bit_order << offset_bit_order);
write(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
}
void SPITester::set_sym_size(uint32_t sym_size, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_sym_size, uint32_t size_sym_size)
{
uint32_t spi_ctrl = 0;
read(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
spi_ctrl &= ~(((1 << size_sym_size) - 1) << offset_sym_size) ;
spi_ctrl |= (sym_size << offset_sym_size);
write(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
}
void SPITester::set_duplex_mode(SPITester::SpiDuplex duplex, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_duplex, uint32_t size_duplex)
{
uint32_t spi_ctrl = 0;
read(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
spi_ctrl &= ~(((1 << size_duplex) - 1) << offset_duplex);
spi_ctrl |= (duplex << offset_duplex);
write(addr_spi_ctrl, (uint8_t *)&spi_ctrl, size_spi_ctrl);
}
void SPITester::set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt, uint32_t addr_hd_rx_cnt, uint32_t size_hd_rx_cnt, uint32_t addr_hd_tx_cnt, uint32_t size_hd_tx_cnt)
{
write(addr_hd_rx_cnt, (uint8_t *)&rx_cnt, size_hd_rx_cnt);
write(addr_hd_tx_cnt, (uint8_t *)&tx_cnt, size_hd_tx_cnt);
}

View File

@ -0,0 +1,127 @@
/*
* 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 SPI_TESTER_H
#define SPI_TESTER_H
#include "MbedTester.h"
class SPITester: public MbedTester {
public:
enum SpiMode {
Mode0 = 0,
Mode1 = 1,
Mode2 = 2,
Mode3 = 3
};
enum SpiBitOrder {
MSBFirst = 0,
LSBFirst = 1
};
enum SpiDuplex {
FullDuplex = 0,
HalfDuplex = 1
};
SPITester(const PinList *form_factor, const PinList *exclude_pins)
: MbedTester(form_factor, exclude_pins)
{
}
protected:
/*
* Read the number of transfers which have occurred
*
* return The number of SPI transfers that have completed since
* spi was reset.
*/
uint16_t get_transfer_count(uint32_t addr_transfers, uint32_t size_transfers);
/*
* Read a checksum of data send to the tester
*
* param addr_checksum Address of the FPGA checksum reg.
* param size_checksum Size of the FPGA checksum reg.
*
* return The sum of all bytes sent to the tester since reset.
*/
uint32_t get_receive_checksum(uint32_t addr_checksum, uint32_t size_checksum);
/*
* Set the clock mode of the spi_slave module.
*
* param mode Spi clock mode
* param addr_spi_ctrl Address of the FPGA spi control reg.
* param size_spi_ctrl Size of the FPGA FPGA spi control reg.
* param offset_clk_mode Clock mode offset.
* param size_clk_mode Clock mode size.
*/
void set_mode(SpiMode mode, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_clk_mode, uint32_t size_clk_mode);
/*
* Set bit order durring transmission of the spi_slave module.
*
* param bit_order Spi clock mode
* param addr_spi_ctrl Address of the FPGA spi control reg.
* param size_spi_ctrl Size of the FPGA FPGA spi control reg.
* param offset_bit_order Bit order offset.
* param size_bit_order Bit order size.
*/
void set_bit_order(SpiBitOrder bit_order, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_bit_order, uint32_t size_bit_order);
/*
* Set symbol size used durring transmission of the spi_slave module.
*
* param sym_size Spi symbol size
* param addr_spi_ctrl Address of the FPGA spi control reg.
* param size_spi_ctrl Size of the FPGA FPGA spi control reg.
* param offset_sym_size Symbol size offset.
* param size_sym_size Symbol size size.
*/
void set_sym_size(uint32_t sym_size, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_sym_size, uint32_t size_sym_size);
/*
* Set full-duplex/half-duplex transmission mode of the spi_slave module.
*
* param duplex Duplex mode used for the transmission
* param addr_spi_ctrl Address of the FPGA spi control reg.
* param size_spi_ctrl Size of the FPGA FPGA spi control reg.
* param offset_duplex Duplex mode offset.
* param size_duplex Duplex mode size.
*/
void set_duplex_mode(SpiDuplex duplex, uint32_t addr_spi_ctrl, uint32_t size_spi_ctrl, uint32_t offset_duplex, uint32_t size_duplex);
/*
* Set tx/rx symbol count.
*
* tx_cnt TX symbol count
* rx_cnt RX symbol count
* param addr_hd_rx_cnt Address of the FPGA half duplex RX count reg.
* param size_hd_rx_cnt Size of the FPGA half duplex RX count reg.
* param addr_hd_tx_cnt Address of the FPGA half duplex TX count reg.
* param size_hd_tx_cnt Size of the FPGA half duplex TX count reg.
*
* note Required only in Half-Duplex mode.
*/
void set_hd_tx_rx_cnt(uint16_t tx_cnt, uint16_t rx_cnt, uint32_t addr_hd_rx_cnt, uint32_t size_hd_rx_cnt, uint32_t addr_hd_tx_cnt, uint32_t size_hd_tx_cnt);
};
#endif

View File

@ -0,0 +1,137 @@
/*
* 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.
*/
#include "UARTTester.h"
#include "fpga_config.h"
void UARTTester::set_baud(uint32_t baudrate)
{
uint32_t divisor = TESTER_CLOCK_FREQUENCY_HZ / baudrate;
// Baud divisor is only 16 bits
MBED_ASSERT((divisor & 0xFFFF0000) == 0);
write(TESTER_UART_BAUD_DIVISOR, (uint8_t *)&divisor, TESTER_UART_BAUD_DIVISOR_SIZE);
}
void UARTTester::set_bits(uint8_t data_bits)
{
// Check for supported range
MBED_ASSERT((data_bits >= 1) && (data_bits <= 16));
write(TESTER_UART_BIT_COUNT, &data_bits, sizeof(data_bits));
}
void UARTTester::set_stops(uint8_t stop_bits)
{
// Check for supported range
MBED_ASSERT((stop_bits >= 1) && (stop_bits <= 16));
write(TESTER_UART_STOP_COUNT, &stop_bits, sizeof(stop_bits));
}
void UARTTester::set_parity(bool enable, bool odd_n_even)
{
uint8_t parity = (enable ? TESTER_UART_PARITY_ENABLE : 0) |
(odd_n_even ? TESTER_UART_PARITY_ODD_N_EVEN : 0);
write(TESTER_UART_PARITY, &parity, sizeof(parity));
}
void UARTTester::rx_start()
{
uint8_t data = TESTER_UART_RX_CONTROL_ENABLE;
write(TESTER_UART_RX_CONTROL, &data, sizeof(data));
}
void UARTTester::rx_stop()
{
uint8_t data = 0;
write(TESTER_UART_RX_CONTROL, &data, sizeof(data));
}
uint32_t UARTTester::rx_get_checksum()
{
uint32_t checksum = 0;
read(TESTER_UART_RX_CHECKSUM, (uint8_t *)&checksum, sizeof(checksum));
return checksum;
}
uint32_t UARTTester::rx_get_count()
{
uint32_t count = 0;
read(TESTER_UART_RX_COUNT, (uint8_t *)&count, sizeof(count));
return count;
}
uint16_t UARTTester::rx_get_data(int prev)
{
MBED_ASSERT((prev >= 1) && (prev <= 4));
uint16_t data = 0;
read(TESTER_UART_RX_PREV_1 - (prev - 1) * 2, (uint8_t *)&data, sizeof(data));
return data;
}
uint32_t UARTTester::rx_get_parity_errors()
{
uint32_t errors = 0;
read(TESTER_UART_RX_PARITY_ERRORS, (uint8_t *)&errors, sizeof(errors));
return errors;
}
uint32_t UARTTester::rx_get_stop_errors()
{
uint32_t errors = 0;
read(TESTER_UART_RX_STOP_ERRORS, (uint8_t *)&errors, sizeof(errors));
return errors;
}
uint32_t UARTTester::rx_get_framing_errors()
{
uint32_t errors = 0;
read(TESTER_UART_RX_FRAMING_ERRORS, (uint8_t *)&errors, sizeof(errors));
return errors;
}
void UARTTester::tx_start(bool cts_enabled)
{
uint32_t control = TESTER_UART_TX_CONTROL_ENABLE | (cts_enabled ? TESTER_UART_TX_CONTROL_ENABLE_CTS : 0);
write(TESTER_UART_TX_CONTROL, (uint8_t *)&control, sizeof(control));
}
void UARTTester::tx_stop()
{
uint32_t control = 0;
write(TESTER_UART_TX_CONTROL, (uint8_t *)&control, sizeof(control));
}
void UARTTester::tx_set_delay(uint32_t delay_ns)
{
uint32_t delay_clks = (delay_ns + TESTER_CLOCK_PERIOD_NS - 1) / TESTER_CLOCK_PERIOD_NS;
write(TESTER_UART_TX_DELAY, (uint8_t *)&delay_clks, sizeof(delay_clks));
}
void UARTTester::tx_set_count(uint32_t count)
{
write(TESTER_UART_TX_COUNT, (uint8_t *)&count, sizeof(count));
}
void UARTTester::tx_set_next(uint16_t value)
{
write(TESTER_UART_TX_NEXT, (uint8_t *)&value, sizeof(value));
}
void UARTTester::cts_deassert_delay(uint32_t delay_ns)
{
uint32_t delay_clks = delay_ns / TESTER_CLOCK_PERIOD_NS;
write(TESTER_UART_CTS_DEACTIVATE_DELAY, (uint8_t *)&delay_clks, sizeof(delay_clks));
}

View File

@ -0,0 +1,166 @@
/*
* 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 UART_TESTER_H
#define UART_TESTER_H
#include "MbedTester.h"
class UARTTester: public MbedTester {
public:
UARTTester(const PinList *form_factor, const PinList *exclude_pins)
: MbedTester(form_factor, exclude_pins)
{
}
/**
* Set the baudrate for uart TX and RX
*
* @param baudrate Target baudrate in HZ
*/
void set_baud(uint32_t baudrate);
/**
* Set the number of data bits
*
* Supported values for data bits is 1 to 16
*
* @param data_bits The number of data bits in this transfer
*/
void set_bits(uint8_t data_bits);
/**
* Set the number of stop bits
*
* Supported values for stop bits is 1 to 16
*
* @param stop_bits The number of stop bits to end the transfer with
*/
void set_stops(uint8_t stop_bits);
/**
* Enable or disable parity checking
*
* @param enable true to enable parity checking, false to disable it
* @param odd_n_even true of odd parity, false for even
*/
void set_parity(bool enable, bool odd_n_even);
/**
* Enable UART reception
*/
void rx_start();
/**
* Disable UART reception
*/
void rx_stop();
/**
* Get the sum of all bytes received
*
* @return the sum of all bytes received
*/
uint32_t rx_get_checksum();
/**
* Get the number of bytes received
*
* @return the number of bytes received
*/
uint32_t rx_get_count();
/**
* Get the previous data(s) sent
*
* @param prev index of data to get 1 for the previous
* @return data
*/
uint16_t rx_get_data(int prev = 1);
/**
* Get the number of parity errors that have occurred
*
* @return number of parity errors that have occurred
*/
uint32_t rx_get_parity_errors();
/**
* Get the number of stop errors that have occurred
*
* @return number of stop errors that have occurred
*/
uint32_t rx_get_stop_errors();
/**
* Get the number of framing errors that have occurred
*
* @return number of framing errors that have occurred
*/
uint32_t rx_get_framing_errors();
/**
* Start UART transmission
*/
void tx_start(bool cts_enabled = false);
/**
* Stop UART transmission
*/
void tx_stop();
/**
* Set the delay after the tx_start() call and before the actual start
* of UART transmission
*
* @param delay in nanoseconds
*/
void tx_set_delay(uint32_t delay_ns);
/**
* Set the number of bytes to send
*
* @param count Number of bytes to send when started
*/
void tx_set_count(uint32_t count);
/**
* Set next sequence value to send
*
* When TX is started 'count' bytes will be sent. Each value will
* be one greater than the previous.
*
* @param value Next value to send
*/
void tx_set_next(uint16_t value);
/**
* Set the delay seen when deasserting the CTS line
*
* When delay is set to 0 then transmission will be immediately
* stopped when CTS goes to 1.
*
* @param delay in nanoseconds
*/
void cts_deassert_delay(uint32_t delay_ns);
};
#endif

View File

@ -0,0 +1,192 @@
/*
* 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.
*/
#define TESTER_CLOCK_FREQUENCY_HZ 100000000
#define TESTER_CLOCK_PERIOD_NS 10
#define TESTER_CONTROL 0x00000000
#define TESTER_CONTROL_RESET 0x00000000
#define TESTER_CONTROL_RESET_PERIPHERALS (1 << 0)
#define TESTER_CONTROL_RESET_ALL (1 << 1)
#define TESTER_CONTROL_REPROGRAM (1 << 2)
#define TESTER_CONTROL_VERSION 0x00000010
#define TESTER_CONTROL_VERSION_SIZE 4
#define TESTER_REMAP 0x00001000
#define TESTER_SYS_IO 0x00002000
#define TESTER_SYS_IO_MODE (0x000 + 0x00002C00)
#define TESTER_SYS_IO_MODE_DISABLED 0
#define TESTER_SYS_IO_MODE_SPI_SERIAL_FLASH 1
#define TESTER_SYS_IO_MODE_I2C_IO_EXPANDER0 2
#define TESTER_SYS_IO_MODE_I2C_IO_EXPANDER1 3
#define TESTER_SYS_IO_MODE_I2C_IO_EXPANDER2 4
#define TESTER_SYS_IO_PWM_ENABLE (0x001 + 0x00002C00)
#define TESTER_SYS_IO_PWM_PERIOD (0x002 + 0x00002C00)
#define TESTER_SYS_IO_PWM_CYCLES_HIGH (0x006 + 0x00002C00)
#define TESTER_SYS_IO_AN_MUX_ANALOGIN_MEASUREMENT (0x00A + 0x00002C00)
#define TESTER_SYS_IO_NUM_POWER_SAMPLES (0x00C + 0x00002C00)
#define TESTER_SYS_IO_NUM_POWER_CYCLES (0x010 + 0x00002C00)
#define TESTER_SYS_IO_ADC_SNAPSHOT (0x018 + 0x00002C00)
#define TESTER_SYS_IO_SAMPLE_ADC (0x019 + 0x00002C00)
#define TESTER_SYS_IO_ANIN0_MEASUREMENT (0x030 + 0x00002C00)
#define TESTER_SYS_IO_ANIN0_MEASUREMENTS_SUM (0x032 + 0x00002C00)
#define TESTER_SYS_IO_ANIN1_MEASUREMENT (0x03A + 0x00002C00)
#define TESTER_SYS_IO_ANIN1_MEASUREMENTS_SUM (0x03C + 0x00002C00)
#define TESTER_SYS_IO_ANIN2_MEASUREMENT (0x044 + 0x00002C00)
#define TESTER_SYS_IO_ANIN2_MEASUREMENTS_SUM (0x046 + 0x00002C00)
#define TESTER_SYS_IO_ANIN3_MEASUREMENT (0x04E + 0x00002C00)
#define TESTER_SYS_IO_ANIN3_MEASUREMENTS_SUM (0x050 + 0x00002C00)
#define TESTER_PERIPHERAL 0x00100000
#define TESTER_PERIPHERAL_SELECT 0x00100000
#define TESTER_GPIO 0x00101000
#define TESTER_SPI_MASTER 0x00102000
#define TESTER_SPI_MASTER_STARTS 0x00102008
#define TESTER_SPI_MASTER_STOPS 0x00102009
#define TESTER_SPI_MASTER_TRANSFERS 0x0010200A
#define TESTER_SPI_MASTER_TRANSFERS_SIZE 2
#define TESTER_SPI_MASTER_TO_SLAVE_CHECKSUM 0x00102012
#define TESTER_SPI_MASTER_TO_SLAVE_CHECKSUM_SIZE 4
#define TESTER_SPI_MASTER_CTRL 0x00102016
#define TESTER_SPI_MASTER_CTRL_SIZE 2
#define TESTER_SPI_MASTER_HD_TX_CNT 0x00102018
#define TESTER_SPI_MASTER_HD_TX_CNT_SIZE 2
#define TESTER_SPI_MASTER_HD_RX_CNT 0x0010201A
#define TESTER_SPI_MASTER_HD_RX_CNT_SIZE 2
#define TESTER_SPI_MASTER_CS_TO_FIRST_SCLK_CNT 0x0010201C
#define TESTER_SPI_MASTER_CS_TO_FIRST_SCLK_CNT_SIZE 4
#define TESTER_SPI_MASTER_LAST_SCLK_TO_CS_CNT 0x00102020
#define TESTER_SPI_MASTER_LAST_SCLK_TO_CS_CNT_SIZE 4
#define TESTER_SPI_MASTER_CLK_MODE_OFFSET 0
#define TESTER_SPI_MASTER_CLK_MODE_SIZE 2
#define TESTER_SPI_MASTER_BIT_ORDER_OFFSET 2
#define TESTER_SPI_MASTER_BIT_ORDER_SIZE 1
#define TESTER_SPI_MASTER_DUPLEX_OFFSET 3
#define TESTER_SPI_MASTER_DUPLEX_SIZE 1
#define TESTER_SPI_MASTER_SYM_SIZE_OFFSET 4
#define TESTER_SPI_MASTER_SYM_SIZE_SIZE 6
#define TESTER_SPI_SLAVE 0x00106000
#define TESTER_SPI_SLAVE_STARTS 0x00106008
#define TESTER_SPI_SLAVE_STOPS 0x00106009
#define TESTER_SPI_SLAVE_TRANSFERS 0x0010600A
#define TESTER_SPI_SLAVE_TRANSFERS_SIZE 2
#define TESTER_SPI_SLAVE_TO_MASTER_CHECKSUM 0x00106015
#define TESTER_SPI_SLAVE_TO_MASTER_CHECKSUM_SIZE 4
#define TESTER_SPI_SLAVE_CTRL 0x00106019
#define TESTER_SPI_SLAVE_CTRL_SIZE 2
#define TESTER_SPI_SLAVE_HD_TX_CNT 0x0010601B
#define TESTER_SPI_SLAVE_HD_TX_CNT_SIZE 2
#define TESTER_SPI_SLAVE_HD_RX_CNT 0x0010601D
#define TESTER_SPI_SLAVE_HD_RX_CNT_SIZE 2
#define TESTER_SPI_SLAVE_CLK_DIV 0x0010601F
#define TESTER_SPI_SLAVE_CLK_DIV_SIZE 2
#define TESTER_SPI_SLAVE_NUM_OF_SYMBOLS 0x00106021
#define TESTER_SPI_SLAVE_NUM_OF_SYMBOLS_SIZE 2
#define TESTER_SPI_SLAVE_START_DELAY_US 0x00106023
#define TESTER_SPI_SLAVE_START_DELAY_US_SIZE 1
#define TESTER_SPI_SLAVE_SYM_DELAY_TICKS 0x00106024
#define TESTER_SPI_SLAVE_SYM_DELAY_TICKS_SIZE 2
#define TESTER_SPI_SLAVE_CLK_MODE_OFFSET 0
#define TESTER_SPI_SLAVE_CLK_MODE_SIZE 2
#define TESTER_SPI_SLAVE_BIT_ORDER_OFFSET 2
#define TESTER_SPI_SLAVE_BIT_ORDER_SIZE 1
#define TESTER_SPI_SLAVE_DUPLEX_OFFSET 3
#define TESTER_SPI_SLAVE_DUPLEX_SIZE 1
#define TESTER_SPI_SLAVE_SYM_SIZE_OFFSET 4
#define TESTER_SPI_SLAVE_SYM_SIZE_SIZE 6
#define TESTER_SPI_SLAVE_START_REQUEST_OFFSET 10
#define TESTER_SPI_SLAVE_START_REQUEST_SIZE 1
#define TESTER_IO_METRICS 0x00103000
#define TESTER_IO_METRICS_CTRL 0x00103000
#define TESTER_IO_METRICS_CTRL_ACTIVE_BIT (1 << 0)
#define TESTER_IO_METRICS_CTRL_RESET_BIT (1 << 1)
#define TESTER_IO_METRICS_BASE(i) (0x00103040 + 0x40 * (i))
#define TESTER_IO_METRICS_MIN_PULSE_LOW(i) (TESTER_IO_METRICS_BASE(i) + 0x00)
#define TESTER_IO_METRICS_MIN_PULSE_LOW_SIZE 4
#define TESTER_IO_METRICS_MIN_PULSE_HIGH(i) (TESTER_IO_METRICS_BASE(i) + 0x04)
#define TESTER_IO_METRICS_MIN_PULSE_HIGH_SIZE 4
#define TESTER_IO_METRICS_MAX_PULSE_LOW(i) (TESTER_IO_METRICS_BASE(i) + 0x08)
#define TESTER_IO_METRICS_MAX_PULSE_LOW_SIZE 4
#define TESTER_IO_METRICS_MAX_PULSE_HIGH(i) (TESTER_IO_METRICS_BASE(i) + 0x0C)
#define TESTER_IO_METRICS_MAX_PULSE_HIGH_SIZE 4
#define TESTER_IO_METRICS_RISING_EDGES(i) (TESTER_IO_METRICS_BASE(i) + 0x10)
#define TESTER_IO_METRICS_RISING_EDGES_SIZE 4
#define TESTER_IO_METRICS_FALLING_EDGES(i) (TESTER_IO_METRICS_BASE(i) + 0x14)
#define TESTER_IO_METRICS_FALLING_EDGES_SIZE 4
#define TESTER_UART_CONTROL (0x000 + 0x00104000)
#define TESTER_UART_CONTROL_SIZE 4
#define TESTER_UART_BAUD_DIVISOR (0x004 + 0x00104000)
#define TESTER_UART_BAUD_DIVISOR_SIZE 2
#define TESTER_UART_BIT_COUNT (0x010 + 0x00104000)
#define TESTER_UART_BIT_COUNT_SIZE 1
#define TESTER_UART_STOP_COUNT (0x011 + 0x00104000)
#define TESTER_UART_STOP_COUNT_SIZE 1
#define TESTER_UART_PARITY (0x012 + 0x00104000)
#define TESTER_UART_PARITY_SIZE 1
#define TESTER_UART_PARITY_ENABLE (1 << 0)
#define TESTER_UART_PARITY_ODD_N_EVEN (1 << 1)
#define TESTER_UART_RX_CONTROL (0x100 + 0x00104000)
#define TESTER_UART_RX_CONTROL_SIZE 4
#define TESTER_UART_RX_CONTROL_ENABLE (1 << 0)
#define TESTER_UART_RX_CONTROL_RESET (1 << 1)
#define TESTER_UART_RX_CHECKSUM (0x104 + 0x00104000)
#define TESTER_UART_RX_CHECKSUM_SIZE 4
#define TESTER_UART_RX_COUNT (0x108 + 0x00104000)
#define TESTER_UART_RX_COUNT_SIZE 4
#define TESTER_UART_RX_PARITY_ERRORS (0x10C + 0x00104000)
#define TESTER_UART_RX_PARITY_ERRORS_SIZE 4
#define TESTER_UART_RX_STOP_ERRORS (0x110 + 0x00104000)
#define TESTER_UART_RX_STOP_ERRORS_SIZE 4
#define TESTER_UART_RX_FRAMING_ERRORS (0x114 + 0x00104000)
#define TESTER_UART_RX_FRAMING_ERRORS_SIZE 4
#define TESTER_UART_RX_PREV_4 (0x118 + 0x00104000)
#define TESTER_UART_RX_PREV_4_SIZE 2
#define TESTER_UART_RX_PREV_3 (0x11A + 0x00104000)
#define TESTER_UART_RX_PREV_3_SIZE 2
#define TESTER_UART_RX_PREV_2 (0x11C + 0x00104000)
#define TESTER_UART_RX_PREV_2_SIZE 2
#define TESTER_UART_RX_PREV_1 (0x11E + 0x00104000)
#define TESTER_UART_RX_PREV_1_SIZE 2
#define TESTER_UART_TX_CONTROL (0x200 + 0x00104000)
#define TESTER_UART_TX_CONTROL_SIZE 4
#define TESTER_UART_TX_CONTROL_ENABLE (1 << 0)
#define TESTER_UART_TX_CONTROL_RESET (1 << 1)
#define TESTER_UART_TX_CONTROL_ENABLE_CTS (1 << 2)
#define TESTER_UART_TX_COUNT (0x204 + 0x00104000)
#define TESTER_UART_TX_COUNT_SIZE 4
#define TESTER_UART_TX_NEXT (0x208 + 0x00104000)
#define TESTER_UART_TX_NEXT_SIZE 2
#define TESTER_UART_CTS_DEACTIVATE_DELAY (0x210 + 0x00104000)
#define TESTER_UART_CTS_DEACTIVATE_DELAY_SIZE 4
#define TESTER_UART_TX_DELAY (0x214 + 0x00104000)
#define TESTER_UART_TX_DELAY_SIZE 4
#define TESTER_I2C_STARTS (0x000 + 0x00105000)
#define TESTER_I2C_STOPS (0x001 + 0x00105000)
#define TESTER_I2C_ACKS (0x002 + 0x00105000)
#define TESTER_I2C_NACKS (0x004 + 0x00105000)
#define TESTER_I2C_TRANSFERS (0x006 + 0x00105000)
#define TESTER_I2C_TRANSFERS_SIZE 2
#define TESTER_I2C_TO_SLAVE_CHECKSUM (0x008 + 0x00105000)
#define TESTER_I2C_TO_SLAVE_CHECKSUM_SIZE 4
#define TESTER_I2C_STATE_NUM (0x00C + 0x00105000)
#define TESTER_I2C_NUMBER_DEV_ADDR_MATCHES (0x00D + 0x00105000)
#define TESTER_I2C_DEVICE_ADDRESS (0x00E + 0x00105000)
#define TESTER_I2C_SET_SDA (0x010 + 0x00105000)
#define TESTER_I2C_PREV_TO_SLAVE_4 (0x011 + 0x00105000)
#define TESTER_I2C_PREV_TO_SLAVE_3 (0x012 + 0x00105000)
#define TESTER_I2C_PREV_TO_SLAVE_2 (0x013 + 0x00105000)
#define TESTER_I2C_PREV_TO_SLAVE_1 (0x014 + 0x00105000)
#define TESTER_I2C_NEXT_FROM_SLAVE (0x015 + 0x00105000)
#define TESTER_I2C_NUM_WRITES (0x016 + 0x00105000)
#define TESTER_I2C_NUM_READS (0x018 + 0x00105000)

View File

@ -0,0 +1,535 @@
/*
* 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 TEST_UTILS_H
#define TEST_UTILS_H
#include <list>
// test function prototypes
typedef void (*TF1)(PinName p0);
typedef void (*TF2)(PinName p0, PinName p1);
typedef void (*TF3)(PinName p0, PinName p1, PinName p2);
typedef void (*TF4)(PinName p0, PinName p1, PinName p2, PinName p3);
typedef void (*TF5)(PinName p0, PinName p1, PinName p2, PinName p3, PinName p4);
template<typename PortType, typename FunctionType, FunctionType f>
struct FunctionCaller {
};
template<typename PortType, TF1 f>
struct FunctionCaller<PortType, TF1, f> {
void operator()(PortType &port)
{
f(port.pins[0]);
}
};
template<typename PortType, TF2 f>
struct FunctionCaller<PortType, TF2, f> {
void operator()(PortType &port)
{
f(port.pins[0], port.pins[1]);
}
};
template<typename PortType, TF3 f>
struct FunctionCaller<PortType, TF3, f> {
void operator()(PortType &port)
{
f(port.pins[0], port.pins[1], port.pins[2]);
}
};
template<typename PortType, TF4 f>
struct FunctionCaller<PortType, TF4, f> {
void operator()(PortType &port)
{
f(port.pins[0], port.pins[1], port.pins[2], port.pins[3]);
}
};
template<typename PortType, TF5 f>
struct FunctionCaller<PortType, TF5, f> {
void operator()(PortType &port)
{
f(port.pins[0], port.pins[1], port.pins[2], port.pins[3], port.pins[4]);
}
};
template <typename PortType>
bool peripheral_comparator(const PortType &port1, const PortType &port2)
{
return port1.peripheral == port2.peripheral;
}
template <typename PortType>
bool peripheral_less(const PortType &port1, const PortType &port2)
{
return port1.peripheral < port2.peripheral;
}
template<typename PortType, typename FormFactorType>
static bool find_port_pins(PortType &port)
{
return pinmap_find_peripheral_pins(FormFactorType::pins(), FormFactorType::restricted_pins(),
port.peripheral, PortType::PinMap::maps, port.ppins, PortType::pin_count);
}
template<typename PortType, typename FormFactorType>
void find_ports(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
{
// Loop through every pin type
for (uint32_t i = 0; i < PortType::pin_count; i++) {
const PinMap *map = PortType::PinMap::maps[i];
const char *pin_type = PortType::PinMap::pin_type_names[i];
// Loop through each pin of a given type
for (; map->pin != NC; map++) {
PortType port;
// Set pin being tested
port.pins[i] = map->pin;
port.peripheral = map->peripheral;
// Only form factor pins can be tested
if (!pinmap_list_has_pin(FormFactorType::pins(), port.pins[i])) {
continue;
}
// Don't test restricted pins
if (pinmap_list_has_pin(FormFactorType::restricted_pins(), port.pins[i])) {
utest_printf("Skipping %s pin %s (%i)\r\n", pin_type,
FormFactorType::pin_to_string(port.pins[i]), port.pins[i]);
continue;
}
// skipp pin searching if single pin port type
if (PortType::pin_count > 1) {
find_port_pins<PortType, FormFactorType>(port);
}
if (port.empty()) {
not_matched_ports.push_back(port);
} else {
matched_ports.push_back(port);
}
}
}
}
template<typename PortType, typename FormFactorType, typename FunctionType, FunctionType f>
void test_all_ports(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
{
typedef typename std::list<PortType>::iterator Iter;
utest_printf("***Testing %s on all form factor ports***\n", PortType::PinMap::name);
const PinList *ff_pins = FormFactorType::pins();
FunctionCaller<PortType, FunctionType, f> call;
if (matched_ports.empty() && not_matched_ports.empty()) {
utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
return;
}
for (uint32_t i = 0; i < ff_pins->count; i++) {
for (Iter it = matched_ports.begin(); it != matched_ports.end(); ++it) {
PortType &port = *it;
for (uint32_t j = 0; j < PortType::pin_count; j++) {
if (ff_pins->pins[i] == port.pins[j]) {
utest_printf("%3s - %s pin tested on port: %s...", FormFactorType::pin_to_string(ff_pins->pins[i]),
PortType::PinMap::pin_type_names[j], port.str());
if (port.status == PortType::StatusNotTested) {
call(port);
port.status = PortType::StatusPass;
}
utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
goto end_port_iteration;
}
}
}
for (Iter it = not_matched_ports.begin(); it != not_matched_ports.end(); ++it) {
PortType &port = *it;
for (uint32_t j = 0; j < PortType::pin_count; j++) {
if (ff_pins->pins[i] == port.pins[j]) {
utest_printf("%3s - Could not find pins to test %s pin %s (%d)\n",
FormFactorType::pin_to_string(ff_pins->pins[i]),
PortType::PinMap::pin_type_names[j],
FormFactorType::pin_to_string(ff_pins->pins[i]),
ff_pins->pins[i]);
goto end_port_iteration;
}
}
}
end_port_iteration:
;
}
}
template<typename PortType, typename FunctionType, FunctionType f>
void test_peripheral(PortType &port)
{
if (port.empty()) {
utest_printf("%d - Could not find pins to test peripheral\n", port.peripheral);
} else {
utest_printf("%d - peripheral tested on port: %s...", port.peripheral, port.str());
if (port.status == PortType::StatusNotTested) {
FunctionCaller<PortType, FunctionType, f> call;
call(port); // run test
port.status = PortType::StatusPass;
}
utest_printf("%s\n", port.status == PortType::StatusPass ? "succeeded" : "failed");
}
}
template<typename PortType, typename FunctionType, FunctionType f>
void test_all_peripherals(std::list<PortType> &matched_ports, std::list<PortType> &not_matched_ports)
{
typedef typename std::list<PortType>::iterator Iter;
utest_printf("***Testing all %s peripherals***\n", PortType::PinMap::name);
if (matched_ports.empty() && not_matched_ports.empty()) {
utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
return;
}
matched_ports.sort(peripheral_less<PortType>);
not_matched_ports.sort(peripheral_less<PortType>);
for (Iter m_it = matched_ports.begin(), nm_it = not_matched_ports.begin();
m_it != matched_ports.end() || nm_it != not_matched_ports.end();) {
if (m_it != matched_ports.end() && nm_it != not_matched_ports.end()) {
if ((*m_it).peripheral < (*nm_it).peripheral) {
test_peripheral<PortType, FunctionType, f>(*m_it);
++m_it;
} else {
test_peripheral<PortType, FunctionType, f>(*nm_it);
++nm_it;
}
} else if (m_it != matched_ports.end()) {
test_peripheral<PortType, FunctionType, f>(*m_it);
++m_it;
} else if (nm_it != not_matched_ports.end()) {
test_peripheral<PortType, FunctionType, f>(*nm_it);
++nm_it;
}
}
}
/**
* Test function for all pinouts of all peripherals of a given type
*
* This template function takes in three template parameters:
* - PortType - The type of peripheral to test
* - FormFactorType - The form factor to test on
* - f - The test function to run.
*
* This function is calls the test function multiple times with
* the appropriate combinations of pins.
*/
template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
void all_ports()
{
std::list<PortType> matched_ports, not_matched_ports;
find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
matched_ports.unique();
not_matched_ports.unique();
test_all_ports<PortType, FormFactorType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
}
/**
* Test function for one pinout of all peripherals of a given type
*
* This template function takes in three template parameters:
* - PortType - The type of peripheral to test
* - FormFactorType - The form factor to test on
* - f - The test function to run.
*
* This function is calls the test function once for each peripheral
* of the given type.
*/
template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
void all_peripherals()
{
std::list<PortType> matched_ports, not_matched_ports;
find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
matched_ports.sort(peripheral_less<PortType>);
not_matched_ports.sort(peripheral_less<PortType>);
matched_ports.unique(peripheral_comparator<PortType>);
not_matched_ports.unique(peripheral_comparator<PortType>);
test_all_peripherals<PortType, typename PortType::TestFunctionType, f>(matched_ports, not_matched_ports);
}
/**
* Test function for one pinout of one peripheral of a given type
*
* This template function takes in three template parameters:
* - PortType - The type of peripheral to test
* - FormFactorType - The form factor to test on
* - f - The test function to run.
*
* This function is calls the test function once for one peripheral
* of the given type.
*/
template<typename PortType, typename FormFactorType, typename PortType::TestFunctionType f>
void one_peripheral()
{
std::list<PortType> matched_ports, not_matched_ports;
find_ports<PortType, FormFactorType>(matched_ports, not_matched_ports);
utest_printf("***Testing one %s pin configuration***\n", PortType::PinMap::name);
if (matched_ports.empty()) {
utest_printf("Could not find pins for %s testing \n", PortType::PinMap::name);
} else {
test_peripheral<PortType, typename PortType::TestFunctionType, f>(matched_ports.front());
}
}
template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
class Port;
template <uint32_t N, typename PinMapType, typename FormFactorType, typename TestFunctionType>
bool operator== (const Port<N, PinMapType, FormFactorType, TestFunctionType> &port1,
const Port<N, PinMapType, FormFactorType, TestFunctionType> &port2);
template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
class Port {
public:
int peripheral;
PinName pins[N];
PinName *ppins[N];
static const uint32_t pin_count = N;
typedef PinMapType PinMap;
typedef FunctionType TestFunctionType;
enum Status { StatusPass, StatusFail, StatusNotTested };
Status status;
Port(): peripheral(NC), status(StatusNotTested)
{
init_pins();
}
Port(const Port &port)
{
init_pins();
copy_from(port);
}
void init_pins()
{
for (uint32_t i = 0; i < N; i++) {
pins[i] = NC;
ppins[i] = &pins[i];
}
}
void copy_from(const Port &port)
{
peripheral = port.peripheral;
status = port.status;
for (uint32_t i = 0; i < N; i++) {
pins[i] = port.pins[i];
}
}
bool empty()
{
if (peripheral == NC) {
return true;
}
for (uint32_t i = 0; i < N; i++) {
if (pins[i] == NC) {
return true;
}
}
return false;
}
const char *str()
{
static char port_str[128];
char pin_str[32];
sprintf(port_str, "peripheral=(%d) ", peripheral);
for (uint32_t i = 0; i < N; i++) {
sprintf(pin_str, "%s=(%s) ", PinMap::pin_type_names[i], FormFactorType::pin_to_string(pins[i]));
strcat(port_str, pin_str);
}
return port_str;
}
friend bool operator==<> (const Port<N, PinMapType, FormFactorType, FunctionType> &port1, const Port<N, PinMapType, FormFactorType, FunctionType> &port2);
};
template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
const uint32_t Port<N, PinMapType, FormFactorType, FunctionType>::pin_count;
template <uint32_t N, typename PinMapType, typename FormFactorType, typename FunctionType>
bool operator== (const Port<N, PinMapType, FormFactorType, FunctionType> &port1, const Port<N, PinMapType, FormFactorType, FunctionType> &port2)
{
if (port1.peripheral != port2.peripheral) {
return false;
}
for (uint32_t i = 0; i < N; i++) {
if (port1.pins[i] != port2.pins[i]) {
return false;
}
}
return true;
}
/**
* This is a convenience class for use with the above templates
*
* This class can be passed as a template parameter to all_ports,
* all_peripherals or one_peripheral to choose test pins from
* the default form factor.
*/
class DefaultFormFactor {
public:
static const PinList *pins()
{
return pinmap_ff_default_pins();
}
static const PinList *restricted_pins()
{
return pinmap_restricted_pins();
}
static const char *pin_to_string(PinName pin)
{
return pinmap_ff_default_pin_to_string(pin);
}
};
/*
* Peripheral port declarations are given below
*
* Each Port type represents a set of pins used by a peripheral.
* The Port typedef is used as a template parameter to the functions
* all_ports, all_peripherals and one_peripheral to select the peripheral
* pin set to use for testing.
*/
#if DEVICE_SPI
#include "spi_api.h"
struct SPIMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *SPIMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap(), spi_master_cs_pinmap() };
const char *const SPIMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
const char *const SPIMaps::name = "SPI";
typedef Port<4, SPIMaps, DefaultFormFactor, TF4> SPIPort;
struct SPINoCSMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *SPINoCSMaps::maps[] = { spi_master_mosi_pinmap(), spi_master_miso_pinmap(), spi_master_clk_pinmap()};
const char *const SPINoCSMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK" };
const char *const SPINoCSMaps::name = "SPI";
typedef Port<3, SPINoCSMaps, DefaultFormFactor, TF3> SPINoCSPort;
struct SPISlaveMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *SPISlaveMaps::maps[] = { spi_slave_mosi_pinmap(), spi_slave_miso_pinmap(), spi_slave_clk_pinmap(), spi_slave_cs_pinmap() };
const char *const SPISlaveMaps::pin_type_names[] = { "MOSI", "MISO", "SCLK", "SSEL" };
const char *const SPISlaveMaps::name = "SPISlave";
typedef Port<4, SPISlaveMaps, DefaultFormFactor, TF4> SPISlavePort;
#endif
#if DEVICE_I2C
#include "i2c_api.h"
struct I2CMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *I2CMaps::maps[] = { i2c_master_sda_pinmap(), i2c_master_scl_pinmap() };
const char *const I2CMaps::pin_type_names[] = { "SDA", "SCL" };
const char *const I2CMaps::name = "I2C";
typedef Port<2, I2CMaps, DefaultFormFactor, TF2> I2CPort;
#endif
#if DEVICE_PWMOUT
#include "pwmout_api.h"
struct PWMMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *PWMMaps::maps[] = { pwmout_pinmap() };
const char *const PWMMaps::pin_type_names[] = { "PWM_OUT" };
const char *const PWMMaps::name = "PWM";
typedef Port<1, PWMMaps, DefaultFormFactor, TF1> PWMPort;
#endif
#if DEVICE_ANALOGIN
#include "analogin_api.h"
struct AnaloginMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *AnaloginMaps::maps[] = { analogin_pinmap() };
const char *const AnaloginMaps::pin_type_names[] = { "ADC_IN" };
const char *const AnaloginMaps::name = "ADC";
typedef Port<1, AnaloginMaps, DefaultFormFactor, TF1> AnaloginPort;
#endif
#if DEVICE_ANALOGOUT
#include "analogout_api.h"
struct AnalogoutMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *AnalogoutMaps::maps[] = { analogout_pinmap() };
const char *const AnalogoutMaps::pin_type_names[] = { "DAC_OUT" };
const char *const AnalogoutMaps::name = "DAC";
typedef Port<1, AnalogoutMaps, DefaultFormFactor, TF1> AnalogoutPort;
#endif
#if DEVICE_SERIAL
struct UARTMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *UARTMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap(), serial_cts_pinmap(), serial_rts_pinmap() };
const char *const UARTMaps::pin_type_names[] = { "TX", "RX", "CLS", "RTS" };
const char *const UARTMaps::name = "UART";
typedef Port<4, UARTMaps, DefaultFormFactor, TF4> UARTPort;
struct UARTNoFCMaps {
static const PinMap *maps[];
static const char *const pin_type_names[];
static const char *const name;
};
const PinMap *UARTNoFCMaps::maps[] = { serial_tx_pinmap(), serial_rx_pinmap() };
const char *const UARTNoFCMaps::pin_type_names[] = { "TX", "RX" };
const char *const UARTNoFCMaps::name = "UART-no-FC";
typedef Port<2, UARTNoFCMaps, DefaultFormFactor, TF2> UARTNoFCPort;
#endif
#endif