Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boards: icev_wireless: document flashing the ice40 fpga #52765

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 82 additions & 3 deletions boards/riscv/icev_wireless/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ features:
+-----------+------------+------------------+
| ADC | on-chip | |
+-----------+------------+------------------+
| FPGA | off-chip | fpga_ice40 |
+-----------+------------+------------------+

Other hardware features have not been enabled yet for this board.

Expand Down Expand Up @@ -188,9 +190,9 @@ For the :code:`Hello, world!` application, follow the instructions below.

Open the serial monitor using the following command:

.. code-block:: console
.. code-block:: bash

$ west espressif monitor
west espressif monitor

After the board has automatically reset and booted, you should see the following
message in the monitor:
Expand All @@ -207,7 +209,7 @@ As with much custom hardware, the ESP32C3 modules require patches to
OpenOCD that are not upstreamed. Espressif maintains their own fork of
the project. The custom OpenOCD can be obtained by running the following extension:

.. code-block:: console
.. code-block:: bash

west espressif install

Expand Down Expand Up @@ -237,12 +239,89 @@ You can debug an application in the usual way. Here is an example for the
:maybe-skip-config:
:goals: debug

Programming the FPGA
====================

Download and save the ICE-V Wireless `default bitstream`_ to the current working directory.

.. code-block:: bash

curl -L -o bitstream.bin 'https://github.com/ICE-V-Wireless/ICE-V-Wireless/blob/main/Firmware/spiffs/bitstream.bin?raw=true'
printf "Bitstream size is 0x%x\n" $(wc -c bitstream.bin | awk '{print $1}')
printf "Bitstream CRC is %s\n" $(crc32 bitstream.bin)
truncate -s %4 bitstream.bin
printf "Rounded bitstream size is 0x%x\n" $(wc -c bitstream.bin | awk '{print $1}')

.. code-block:: console

Bitstream size is 0x1969a
Bitstream CRC is 8d34da6c
Bitstream padded size is 0x1969c

Build and flash the :ref:`flash_shell` application.

.. zephyr-app-commands::
:zephyr-app: samples/drivers/flash_shell
:board: icev_wireless
:maybe-skip-config:
:goals: flash

Open a terminal to the device via USB:

.. code-block:: bash

minicom -D /dev/tty.usbmodem1101 -b 115200

Clear the `image-scratch` partition:

.. code-block:: console

flash erase flash-controller@60002000 0x00210000 0x20000

Prepare to load the ICE-V Wireless bitstream to the `image-scratch` partition:

.. note::

Use the padded bitstream size (0x1969c below), as `flash load` needs every
image padded to a multiple of 4 bytes.

.. code-block:: console

flash load flash-controller@60002000 0x00210000 0x1969c

Transmit the ICE-V Wireless bitstream to the `image-scratch` partition:

.. code-block:: bash

dd if=bitstream.bin of=/dev/tty.usbmodem1101

Although unlikely, it may be possible that the bitstream was corrupted
transferring serially, so it's a good idea to check the CRC value.

.. code-block:: console

crc 0x3c020000 0x1969a


Load the bitstream from flash:

.. note::

Use the unpadded bitstream size (104090 below) for `fpga load`.

.. code-block:: console

fpga load fpga@0 0x3c020000 0x1969a

References
**********

.. _ICE-V Wireless Github Project:
https://github.com/ICE-V-Wireless/ICE-V-Wireless

.. _ICE-V Wireless Default Bitstream:
https://github.com/ICE-V-Wireless/ICE-V-Wireless/blob/main/Firmware/spiffs/bitstream.bin

.. _ESP32-C3-MINI-1 Datasheet:
https://www.espressif.com/sites/default/files/documentation/esp32-c3-mini-1_datasheet_en.pdf

Expand Down
22 changes: 22 additions & 0 deletions boards/riscv/icev_wireless/icev_wireless.dts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@
#size-cells = <0>;
pinctrl-0 = <&spim2_default>;
pinctrl-names = "default";

cs-gpios = <&gpio0 6 (GPIO_PUSH_PULL | GPIO_ACTIVE_LOW)>;

fpga0: fpga@0 {
status = "okay";
compatible = "lattice,ice40-fpga";

reg = <0>;
spi-max-frequency = <1000000>;

load-mode = <1>;
cdone-gpios = <&gpio0 0 0>;
creset-gpios = <&gpio0 1 (GPIO_PUSH_PULL | GPIO_ACTIVE_LOW)>;
clk-gpios = <&gpio0 5 (GPIO_PUSH_PULL | GPIO_ACTIVE_LOW)>;
pico-gpios = <&gpio0 7 (GPIO_PUSH_PULL | GPIO_ACTIVE_LOW)>;
mhz-delay-count = <4>;
gpios-set-reg = <0x60004008>;
gpios-clear-reg = <0x6000400c>;
config-delay-us = <2000>;
leading-clocks = <8>;
trailing-clocks = <160>;
};
};

&gpio0 {
Expand Down
44 changes: 34 additions & 10 deletions drivers/fpga/fpga_ice40.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#define FPGA_ICE40_LEADING_CLOCKS_MIN 8
#define FPGA_ICE40_TRAILING_CLOCKS_MIN 49

#define LOG_LEVEL LOG_LEVEL_DBG
LOG_MODULE_REGISTER(fpga_ice40);

struct fpga_ice40_data {
Expand Down Expand Up @@ -200,6 +201,25 @@ static enum FPGA_status fpga_ice40_get_status(const struct device *dev)
return st;
}

static int wait_for_cdone(const struct fpga_ice40_config *config, size_t timeout)
{
int ret;

for (; timeout > 0; timeout--) {
ret = gpio_pin_get_dt(&config->cdone);
if (ret == 1) {
return 0;
}
if (ret < 0) {
LOG_ERR("failed to read CDONE, %d", ret);
return ret;
}
}

LOG_ERR("CDONE did not go high");
return -EIO;
}

/*
* See iCE40 Family Handbook, Appendix A. SPI Slave Configuration Procedure,
* pp 15-21.
Expand Down Expand Up @@ -246,14 +266,23 @@ static int fpga_ice40_load_gpio(const struct device *dev, uint32_t *image_ptr, u
__ASSERT(ret == 0, "Failed to initialize GPIO: %d", ret);

LOG_DBG("Set CRESET low");
*config->clear |= creset;

LOG_DBG("Delay 1 us");
k_busy_wait(1);

LOG_DBG("Set SPI_CS low");
*config->clear |= (creset | cs);
*config->clear |= cs;

/* Wait a minimum of 200ns */
LOG_DBG("Delay %u us", config->creset_delay_us);
fpga_ice40_delay(2 * config->mhz_delay_count * config->creset_delay_us);
k_busy_wait(1);

__ASSERT(gpio_pin_get_dt(&config->cdone) == 0, "CDONE was not high");
LOG_DBG("Checking CDONE");
ret = wait_for_cdone(config, 100);
if (ret < 0) {
goto unlock;
}

LOG_DBG("Set CRESET high");
*config->set |= creset;
Expand All @@ -278,14 +307,9 @@ static int fpga_ice40_load_gpio(const struct device *dev, uint32_t *image_ptr, u
fpga_ice40_send_clocks(config->mhz_delay_count, config->set, config->clear, clk,
config->trailing_clocks);

LOG_DBG("checking CDONE");
ret = gpio_pin_get_dt(&config->cdone);
LOG_DBG("Checking CDONE");
ret = wait_for_cdone(config, 100);
if (ret < 0) {
LOG_ERR("failed to read CDONE: %d", ret);
goto unlock;
} else if (ret != 1) {
ret = -EIO;
LOG_ERR("CDONE did not go high");
goto unlock;
}

Expand Down
4 changes: 3 additions & 1 deletion samples/drivers/fpga/fpga_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(fpga_controller)

target_sources(app PRIVATE src/main.c)
target_sources(app PRIVATE src/empty.c)
target_sources_ifdef(CONFIG_BOARD_QUICKFEATHER app PRIVATE src/main.c)
target_sources_ifdef(CONFIG_BOARD_ICEV_WIRELESS app PRIVATE src/esp32.c)
12 changes: 12 additions & 0 deletions samples/drivers/fpga/fpga_controller/boards/icev_wireless.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CONFIG_LOG=y
CONFIG_FLASH=y
CONFIG_SHELL=y
CONFIG_SPI=y
CONFIG_PINCTRL=y
CONFIG_ICE40_FPGA=y
CONFIG_FPGA_SHELL=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n
CONFIG_CRC=y
CONFIG_CRC_SHELL=y
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_EOS_S3_FPGA=y
1 change: 0 additions & 1 deletion samples/drivers/fpga/fpga_controller/prj.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
CONFIG_FPGA=y
CONFIG_EOS_S3_FPGA=y
3 changes: 2 additions & 1 deletion samples/drivers/fpga/fpga_controller/prj_shell.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CONFIG_SHELL=y
CONFIG_FPGA=y
CONFIG_EOS_S3_FPGA=y
CONFIG_FPGA_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL_INTERRUPT_DRIVEN=n
CONFIG_BOOT_BANNER=n
CONFIG_CRC=y
CONFIG_CRC_SHELL=y
4 changes: 2 additions & 2 deletions samples/drivers/fpga/fpga_controller/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ common:

tests:
sample.drivers.fpga_controller:
platform_allow: quick_feather
platform_allow: quick_feather icev_wireless
sample.drivers.fpga_controller.shell:
platform_allow: quick_feather
platform_allow: quick_feather icev_wireless
extra_args: CONF_FILE="prj_shell.conf"
Empty file.
29 changes: 29 additions & 0 deletions samples/drivers/fpga/fpga_controller/src/esp32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <esp_spi_flash.h>
#include <soc.h>
#include <zephyr/init.h>
#include <zephyr/device.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/kernel.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/sys/printk.h>

static int esp32_init(void)
{
const void *vaddr = NULL;
__unused esp_err_t esp_err;

Check warning on line 13 in samples/drivers/fpga/fpga_controller/src/esp32.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LINE_SPACING

samples/drivers/fpga/fpga_controller/src/esp32.c:13 Missing a blank line after declarations
spi_flash_mmap_handle_t handle;
size_t paddr = FIXED_PARTITION_OFFSET(scratch_partition);
size_t size = FIXED_PARTITION_SIZE(scratch_partition);

esp_err = spi_flash_mmap(paddr, size, SPI_FLASH_MMAP_DATA, &vaddr, &handle);
if (esp_err != ESP_OK) {
printk("failed to mmap %zx\n", paddr);
return -EIO;
}

printk("esp32: mapped %zu@%zx to %p\n", size, paddr, vaddr);

return 0;
}

SYS_INIT(esp32_init, POST_KERNEL, 42);

Check warning on line 29 in samples/drivers/fpga/fpga_controller/src/esp32.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

MISSING_EOF_NEWLINE

samples/drivers/fpga/fpga_controller/src/esp32.c:29 adding a line without newline at end of file
Loading