# FreeRTOS Example

## Introduction

The FreeRTOS example is a more sophisticated application that runs on top of [FreeRTOS](https://www.freertos.org/), an open-source real-time operating system. The application uses the GPIO controller of RVX to make 2 LEDs blink in a specific pattern with the help of FreeRTOS task scheduler.

## Prerequisites

To run this example you need an FPGA board with at least 2 LEDs and 32KB of Block RAM.

Additionally, you need to have the [RISC-V GNU Toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) installed on your machine to build the example. You can find instructions on how to install the RISC-V GNU Toolchain in the [User Guide](../userguide.md#prerequisites).

## Building the example

Run the commands below to build the FreeRTOS example:

```bash title="1. Clone RVX repository"
git clone https://github.com/rafaelcalcada/rvx
```

```bash title="2. Build the software for the FreeRTOS example"
cd rvx/examples/freertos/software
make PREFIX=/opt/riscv CLOCK_FREQUENCY=<freq_in_hertz>
```

The `PREFIX` variable must specify the folder where the [RISC-V GNU Toolchain](../userguide.md#prerequisites) is installed. You also need to set the `CLOCK_FREQUENCY` variable to match the clock frequency of the FPGA board where the application will run.

A successfull build ends with a message like this:

```title="Successful build report"
Memory init file:   build/freertos.hex
Binary executable:  build/freertos.elf
Disassembly:        build/freertos.objdump

Memory usage report (MEMORY_SIZE = 32K)
      text       data        bss      total filename
     14092        304       9196      23592 freertos.elf
```

The `freertos.hex` file generated by the build process will be used in the next step to initialize the memory of RVX.

## Implementing on an FPGA

<h4>Creating the FreeRTOS module</h4>

Using your preferred text editor, create a Verilog file name `freertos.v` and add the source code below. Make sure to modify `freertos.v` as follows:

- Change the `MEMORY_INIT_FILE` parameter to the absolute path of the `freertos.hex` file you generated in the previous step.
- Change the `CLOCK_FREQUENCY` parameter to the frequency (in Hertz) of the `clock` input.

```verilog title="freertos.v"
module freertos #(
  
  parameter GPIO_WIDTH = 2

  )(

  input   wire clock,
  input   wire reset,
  output  wire [GPIO_WIDTH-1:0] gpio

  );

  // Reset button debouncing
  reg reset_debounced;
  always @(posedge clock) begin
    reset_debounced <= reset;
  end

  rvx #(

  // Please adjust these parameters accordingly
  .CLOCK_FREQUENCY          (50000000                   ),
  .MEMORY_SIZE              (32768                      ),
  .MEMORY_INIT_FILE         ("/path/to/freertos.hex"    ),
  .GPIO_WIDTH               (GPIO_WIDTH                 )

  ) rvx_instance (

  .clock                    (clock                      ),
  .reset                    (reset_debounced            ),
  .gpio_output              (gpio                       ),

  // Unused inputs need to be hardwired to zero
  .halt                     (1'b0                       ),
  .uart_rx                  (1'b0                       ),
  .gpio_input               ({GPIO_WIDTH{1'b0}}         ),
  .poci                     (1'b0                       ),

  // Unused outputs can be left open
  .uart_tx                  (                           ),  
  .gpio_oe                  (                           ),
  .sclk                     (                           ),
  .pico                     (                           ),  
  .cs                       (                           ));

endmodule
```

---

<h4>Synthesizing the FreeRTOS module</h4>

To implement the `freertos.v` module on your FPGA, follow the steps below:

1. Open the EDA tool provided by your FPGA vendor (e.g., AMD Vivado, Intel Quartus, Lattice iCEcube).

2. Include `freertos.v` to the project and all files in the `hardware/` folder of RVX repository.

3. Create a design constraints file and map the ports of `freertos.v` to the corresponding devices on the FPGA board.

    - Map the `gpio` outputs to 2 LEDs
    - Map the `reset` input to a push-button or switch
    - Map the `clock` input to the clock source

4. Run the synthesis process.

4. Generate the bitstream and, once completed, program the FPGA with it.

The LEDs should start blinking once you've finished programming the FPGA!

## Featured boards

We provide project files for some featured FPGA boards. If you have one of the boards listed below, please follow the specific steps for your board:

### Arty A7

- Build the FreeRTOS application as instructed in [Building the example](#building-the-example)

    Use `CLOCK_FREQUENCY=50000000`.

- On AMD Vivado, click __Tools / Run Tcl Script__

    Select `examples/freertos/boards/arty_a7/create_project_arty_a7_<variant>.tcl`, where `<variant>` is the variant of your board (either 35T or 100T).

- Click **Generate Bitstream** and program the FPGA as usual
- The LEDs should start blinking once you've finished programming the FPGA!

### Cmod A7

- Build the FreeRTOS application as instructed in [Building the example](#building-the-example)

    Use `CLOCK_FREQUENCY=12000000`.

- On AMD Vivado, click __Tools / Run Tcl Script__

    Select `examples/freertos/boards/cmod_a7/create_project_cmod_a7.tcl`.

- Click **Generate Bitstream** and program the FPGA as usual
- The LEDs should start blinking once you've finished programming the FPGA!

</br>
</br>