2021-06-26 15:24:07 +02:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
2020-03-06 09:05:57 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2020 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef JTAG_H
|
|
|
|
|
#define JTAG_H
|
2022-10-15 16:17:32 +02:00
|
|
|
|
2020-03-06 09:05:57 +01:00
|
|
|
#include <iostream>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2020-03-07 11:44:17 +01:00
|
|
|
#include "board.hpp"
|
2020-03-07 10:56:34 +01:00
|
|
|
#include "cable.hpp"
|
2020-03-06 09:05:57 +01:00
|
|
|
#include "jtagInterface.hpp"
|
|
|
|
|
|
|
|
|
|
class Jtag {
|
|
|
|
|
public:
|
2023-04-15 08:20:05 +02:00
|
|
|
Jtag(const cable_t &cable, const jtag_pins_conf_t *pin_conf,
|
|
|
|
|
const std::string &dev,
|
2022-04-11 06:53:22 +02:00
|
|
|
const std::string &serial, uint32_t clkHZ, int8_t verbose,
|
2022-10-06 07:07:17 +02:00
|
|
|
const std::string &ip_adr, int port,
|
2022-03-11 07:45:48 +01:00
|
|
|
const bool invert_read_edge = false,
|
2022-01-13 07:42:14 +01:00
|
|
|
const std::string &firmware_path = "");
|
2020-03-06 09:05:57 +01:00
|
|
|
~Jtag();
|
|
|
|
|
|
|
|
|
|
/* maybe to update */
|
|
|
|
|
int setClkFreq(uint32_t clkHZ) { return _jtag->setClkFreq(clkHZ);}
|
2021-05-15 08:46:21 +02:00
|
|
|
uint32_t getClkFreq() { return _jtag->getClkFreq();}
|
2020-03-06 09:05:57 +01:00
|
|
|
|
2021-05-15 12:25:39 +02:00
|
|
|
/*!
|
|
|
|
|
* \brief scan JTAG chain to obtain IDCODE. Fill
|
|
|
|
|
* a vector with all idcode and another
|
|
|
|
|
* vector with irlength
|
|
|
|
|
* \return number of devices found
|
|
|
|
|
*/
|
2023-09-18 13:31:42 +02:00
|
|
|
int detectChain(unsigned int max_dev);
|
2021-05-15 12:25:39 +02:00
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief return list of devices in the chain
|
|
|
|
|
* \return list of devices
|
|
|
|
|
*/
|
|
|
|
|
std::vector<int> get_devices_list() {return _devices_list;}
|
|
|
|
|
|
2021-08-18 07:39:23 +02:00
|
|
|
/*!
|
|
|
|
|
* \brief return current selected device idcode
|
|
|
|
|
* \return device idcode
|
|
|
|
|
*/
|
|
|
|
|
uint32_t get_target_device_id() {return _devices_list[device_index];}
|
|
|
|
|
|
2021-05-15 12:25:39 +02:00
|
|
|
/*!
|
|
|
|
|
* \brief set index for targeted FPGA
|
|
|
|
|
* \param[in] index: index in the chain
|
|
|
|
|
* \return -1 if index is out of bound, index otherwise
|
|
|
|
|
*/
|
|
|
|
|
uint16_t device_select(uint16_t index);
|
2022-01-13 07:42:14 +01:00
|
|
|
/*!
|
|
|
|
|
* \brief inject a device into list at the begin
|
|
|
|
|
* \param[in] device_id: idcode
|
|
|
|
|
* \param[in] irlength: device irlength
|
|
|
|
|
* \return false if fails
|
|
|
|
|
*/
|
|
|
|
|
bool insert_first(uint32_t device_id, uint16_t irlength);
|
2020-03-06 09:05:57 +01:00
|
|
|
|
2023-02-25 17:15:25 +01:00
|
|
|
/*!
|
|
|
|
|
* \brief return a pointer to the transport subclass
|
|
|
|
|
* \return a pointer instance of JtagInterface
|
|
|
|
|
*/
|
|
|
|
|
JtagInterface *get_ll_class() {return _jtag;}
|
2023-08-10 12:50:26 +02:00
|
|
|
|
2020-03-06 09:05:57 +01:00
|
|
|
enum tapState_t {
|
|
|
|
|
TEST_LOGIC_RESET = 0,
|
|
|
|
|
RUN_TEST_IDLE = 1,
|
|
|
|
|
SELECT_DR_SCAN = 2,
|
|
|
|
|
CAPTURE_DR = 3,
|
|
|
|
|
SHIFT_DR = 4,
|
|
|
|
|
EXIT1_DR = 5,
|
|
|
|
|
PAUSE_DR = 6,
|
|
|
|
|
EXIT2_DR = 7,
|
|
|
|
|
UPDATE_DR = 8,
|
|
|
|
|
SELECT_IR_SCAN = 9,
|
|
|
|
|
CAPTURE_IR = 10,
|
|
|
|
|
SHIFT_IR = 11,
|
|
|
|
|
EXIT1_IR = 12,
|
|
|
|
|
PAUSE_IR = 13,
|
|
|
|
|
EXIT2_IR = 14,
|
|
|
|
|
UPDATE_IR = 15,
|
2023-09-07 10:29:46 +02:00
|
|
|
UNKNOWN = 16,
|
2020-03-06 09:05:57 +01:00
|
|
|
};
|
2023-08-10 16:36:18 +02:00
|
|
|
|
|
|
|
|
int shiftIR(unsigned char *tdi, unsigned char *tdo, int irlen,
|
2023-08-10 12:50:26 +02:00
|
|
|
tapState_t end_state = RUN_TEST_IDLE);
|
2023-08-10 16:36:18 +02:00
|
|
|
int shiftIR(unsigned char tdi, int irlen,
|
2023-08-10 12:50:26 +02:00
|
|
|
tapState_t end_state = RUN_TEST_IDLE);
|
2023-08-10 16:36:18 +02:00
|
|
|
int shiftDR(const uint8_t *tdi, unsigned char *tdo, int drlen,
|
2023-08-10 12:50:26 +02:00
|
|
|
tapState_t end_state = RUN_TEST_IDLE);
|
2023-08-10 16:36:18 +02:00
|
|
|
int read_write(const uint8_t *tdi, unsigned char *tdo, int len, char last);
|
|
|
|
|
|
|
|
|
|
void toggleClk(int nb);
|
|
|
|
|
void go_test_logic_reset();
|
2023-08-10 12:50:26 +02:00
|
|
|
void set_state(tapState_t newState);
|
2023-08-10 16:36:18 +02:00
|
|
|
int flushTMS(bool flush_buffer = false);
|
|
|
|
|
void flush() {flushTMS(); _jtag->flush();}
|
|
|
|
|
void setTMS(unsigned char tms);
|
|
|
|
|
|
2020-03-06 09:05:57 +01:00
|
|
|
const char *getStateName(tapState_t s);
|
|
|
|
|
|
|
|
|
|
/* utilities */
|
2021-10-03 08:22:35 +02:00
|
|
|
void setVerbose(int8_t verbose){_verbose = verbose;}
|
2020-03-06 09:05:57 +01:00
|
|
|
|
2021-12-10 12:12:32 +01:00
|
|
|
JtagInterface *_jtag;
|
|
|
|
|
|
2020-03-06 09:05:57 +01:00
|
|
|
private:
|
2022-01-13 07:34:00 +01:00
|
|
|
/*!
|
|
|
|
|
* \brief search in fpga_list and misc_dev_list for a device with idcode
|
|
|
|
|
* if found insert idcode and irlength in _devices_list and
|
|
|
|
|
* _irlength_list
|
|
|
|
|
* \param[in] idcode: device idcode
|
|
|
|
|
* \return false if not found, true otherwise
|
|
|
|
|
*/
|
|
|
|
|
bool search_and_insert_device_with_idcode(uint32_t idcode);
|
2023-07-30 08:45:57 +02:00
|
|
|
bool _verbose;
|
2023-08-10 12:50:26 +02:00
|
|
|
tapState_t _state;
|
2020-03-06 09:05:57 +01:00
|
|
|
int _tms_buffer_size;
|
|
|
|
|
int _num_tms;
|
|
|
|
|
unsigned char *_tms_buffer;
|
|
|
|
|
std::string _board_name;
|
2021-05-15 12:25:39 +02:00
|
|
|
|
|
|
|
|
int device_index; /*!< index for targeted FPGA */
|
|
|
|
|
std::vector<int32_t> _devices_list; /*!< ordered list of devices idcode */
|
|
|
|
|
std::vector<int16_t> _irlength_list; /*!< ordered list of irlength */
|
2020-03-06 09:05:57 +01:00
|
|
|
};
|
|
|
|
|
#endif
|