|
@@ -147,15 +147,41 @@ void fpga_service_stop(void)
|
|
|
|
|
|
#define FPGA_HDR_ADDR 0x40000000
|
|
|
|
|
|
-static esp_err_t fpga_io(uint8_t cmd, uint32_t addr, void *data, size_t len)
|
|
|
+static esp_err_t fpga_io_write(uint8_t cmd, uint32_t addr,
|
|
|
+ const void *data, size_t len)
|
|
|
{
|
|
|
spi_transaction_ext_t trans;
|
|
|
esp_err_t err;
|
|
|
|
|
|
- if ((len|addr) & 3) {
|
|
|
- printf("[FPGA] ERROR: I/O must be aligned dwords\n");
|
|
|
- return ESP_FAIL;
|
|
|
- }
|
|
|
+ if (!len)
|
|
|
+ return ESP_OK;
|
|
|
+
|
|
|
+ memset(&trans, 0, sizeof trans);
|
|
|
+ trans.base.flags =
|
|
|
+ SPI_TRANS_MODE_DIO |
|
|
|
+ SPI_TRANS_MULTILINE_CMD |
|
|
|
+ SPI_TRANS_MULTILINE_ADDR;
|
|
|
+
|
|
|
+ trans.base.cmd = cmd | ~FPGA_CMD_RD;
|
|
|
+ trans.base.addr = addr;
|
|
|
+ trans.base.tx_buffer = data;
|
|
|
+ trans.base.length = len << 3;
|
|
|
+
|
|
|
+ xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ err = spi_device_transmit(spi_handle, (spi_transaction_t *)&trans);
|
|
|
+ xSemaphoreGive(spi_mutex);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static esp_err_t fpga_io_read(uint8_t cmd, uint32_t addr,
|
|
|
+ void *data, size_t len)
|
|
|
+{
|
|
|
+ spi_transaction_ext_t trans;
|
|
|
+ esp_err_t err;
|
|
|
+
|
|
|
+ if (!len)
|
|
|
+ return ESP_OK;
|
|
|
|
|
|
memset(&trans, 0, sizeof trans);
|
|
|
trans.base.flags =
|
|
@@ -163,19 +189,13 @@ static esp_err_t fpga_io(uint8_t cmd, uint32_t addr, void *data, size_t len)
|
|
|
SPI_TRANS_VARIABLE_DUMMY |
|
|
|
SPI_TRANS_MULTILINE_CMD |
|
|
|
SPI_TRANS_MULTILINE_ADDR;
|
|
|
- trans.command_bits = 8;
|
|
|
- trans.address_bits = 32;
|
|
|
-
|
|
|
- trans.base.cmd = cmd;
|
|
|
- trans.base.addr = addr;
|
|
|
- if (cmd & FPGA_CMD_RD) {
|
|
|
- trans.dummy_bits = 16; /* 16 cycles = 32 bits */
|
|
|
- trans.base.rx_buffer = data;
|
|
|
- trans.base.rxlength = len << 3;
|
|
|
- } else {
|
|
|
- trans.base.tx_buffer = data;
|
|
|
- trans.base.length = len << 3;
|
|
|
- }
|
|
|
+
|
|
|
+ trans.base.cmd = cmd | FPGA_CMD_RD;
|
|
|
+ trans.base.addr = addr;
|
|
|
+ trans.base.rx_buffer = data;
|
|
|
+ /* Emulate partial word read by adding dummy bits for offset */
|
|
|
+ trans.dummy_bits = 16 + ((addr & 3) << 2);
|
|
|
+ trans.base.rxlength = len << 3;
|
|
|
|
|
|
xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
err = spi_device_transmit(spi_handle, (spi_transaction_t *)&trans);
|
|
@@ -184,6 +204,27 @@ static esp_err_t fpga_io(uint8_t cmd, uint32_t addr, void *data, size_t len)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static uint32_t fpga_io_status(void)
|
|
|
+{
|
|
|
+ spi_transaction_ext_t trans;
|
|
|
+ esp_err_t err;
|
|
|
+
|
|
|
+ memset(&trans, 0, sizeof trans);
|
|
|
+ trans.base.flags =
|
|
|
+ SPI_TRANS_MODE_DIO |
|
|
|
+ SPI_TRANS_MULTILINE_CMD |
|
|
|
+ SPI_TRANS_MULTILINE_ADDR |
|
|
|
+ SPI_TRANS_USE_RXDATA;
|
|
|
+
|
|
|
+ trans.base.cmd = FPGA_CMD_RD;
|
|
|
+ trans.base.rxlength = 32;
|
|
|
+
|
|
|
+ xSemaphoreTake(spi_mutex, portMAX_DELAY);
|
|
|
+ err = spi_device_transmit(spi_handle, (spi_transaction_t *)&trans);
|
|
|
+ xSemaphoreGive(spi_mutex);
|
|
|
+
|
|
|
+ return err ? 0 : ntohl(*(const uint32_t *)&trans.base.rx_data);
|
|
|
+}
|
|
|
|
|
|
static void fpga_service_task(void *dummy)
|
|
|
{
|
|
@@ -191,23 +232,27 @@ static void fpga_service_task(void *dummy)
|
|
|
struct dram_io_head head;
|
|
|
|
|
|
/* If the FPGA is already up, need to issue our own active handshake */
|
|
|
- fpga_io(FPGA_CMD_WR|FPGA_CMD_IRQ(RV_IRQ_HELLO), 0, NULL, 0);
|
|
|
+ fpga_io_write(FPGA_CMD_IRQ(RV_IRQ_HELLO), 0, NULL, 0);
|
|
|
|
|
|
while (1) {
|
|
|
while (!digitalRead(PIN_FPGA_INT)) {
|
|
|
printf("[FPGA] FPGA signals ready\n");
|
|
|
|
|
|
- fpga_io(FPGA_CMD_RD|FPGA_CMD_ACK(ESP_IRQ_READY), FPGA_HDR_ADDR,
|
|
|
- &head, sizeof head);
|
|
|
+ uint32_t status = fpga_io_status();
|
|
|
+ printf("[FPGA] Link status bits = 0x%08x\n", status);
|
|
|
+
|
|
|
+ fpga_io_read(FPGA_CMD_ACK(ESP_IRQ_READY), FPGA_HDR_ADDR,
|
|
|
+ &head, sizeof head);
|
|
|
|
|
|
if (head.magic == DRAM_IO_MAGIC && head.hlen >= sizeof head) {
|
|
|
- printf("[FPGA] Ready, board = %u.%u\n",
|
|
|
- (uint8_t)(head.board >> 24), (uint8_t)(head.board >> 16));
|
|
|
+ printf("[FPGA] Ready, board = %u.%u fixes %02x fpga %u\n",
|
|
|
+ head.board.major, head.board.minor,
|
|
|
+ head.board.fixes, head.board.fpga);
|
|
|
}
|
|
|
|
|
|
- char signature_string[head.signature_len + 3];
|
|
|
- fpga_io(FPGA_CMD_RD, (size_t)head.signature,
|
|
|
- signature_string, (head.signature_len + 3) & ~3);
|
|
|
+ char signature_string[head.signature_len+1];
|
|
|
+ fpga_io_read(0, (size_t)head.signature,
|
|
|
+ signature_string, head.signature_len);
|
|
|
signature_string[head.signature_len] = '\0';
|
|
|
|
|
|
printf("[FPGA] \"%s\"\n", signature_string);
|