Pre-evaluation of Caravel SoC created with eFabless MPW

Marmot temperature sensor demo



Version:2025/02/25

Table of Contents:

  1. Temperature Sensor Demo Configuration
  2. Temperature Acquisition via I2C Control
  3. Displaying on 7-Segment LED via GPIO
  4. Operation of QSPI Flash in Dual/Quad mode

1. Temperature Sensor Demo Configuration

1.1. Demo Overview

Objective:

Confirm the operation of I2C, GPIO, and SPI supported by Marmot (SPI is excluded in this demo).

Processing
  1. Acquire data from the BME280 via I2C.
  2. Calculate temperature from the acquired data.
  3. Display temperature on a 7-segment LED via GPIO.
Configuration

Caravel

1.2. Demo Results

Actual demo appearance

Caravel

2. Temperature Acquisition via I2C Control

2.1. Marmot's I2C Specification

Specifications of Marmot's I2C controller
  • • The I2C controller specifications for Marmot are believed to be nearly identical to those of SiFive's Freedom E310.
    The I2C specifications are not documented in the Freedom E310 manual.
    Thus, it was developed with reference to Freedom's I2C.
  • • Freedom implements OpenCore I2C described in Chisel.
  • • he implementation source for Freedom is available at:

https://github.com/sifive/sifive-blocks/tree/a0da03f5a500917e71002a4b427893a49decc775/src/main/scala/devices/i2c

I2C Initialization
I2C0_REG(OC_I2C_PRER_LO) = 0x0f; I2C0_REG(OC_I2C_PRER_HI) = 0x0; I2C0_REG(OC_I2C_CTR) = OC_I2C_EN;

Pink lines: Prescaler settings

Yellow lines: Enabling 2C

2.2. Marmot's I2C Control

Marmot's I2C write/read functions.

Caravel

2.3. Specifications of Temperature Sensor BME280

Features of BME280:
  • • Capable of measuring temperature, humidity, and pressure.
  • • I2C interface.
Reference Documents:
Documents Location
Documentation https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280
Sample Code https://github.com/boschsensortec/BME280_SensorAPI
Source Implementation Guidelines:
  • • Implemented with reference to sample code.
  • • Calibration processes were directly copied from the sample code.

2.4. Control of BME280

Control flow for BME280.

Caravel

3. Display on 7-Segment LED via GPIO Control

3.1. Marmot's GPIO Specifications

The GPIO specifications are found in the Freedom FE310 Manual

Chapter 10, Figure 10.

  1. GPIO Selection:
    • • When IOF_EN is 0: GPIO mode.
    • • When IOF_EN is 1: Peripheral mode (IO Function).
  2. GPIO Input:
    • • When IE is 1: Values can be read from IOF_VAL.
    • • When IE is 0: IOF_VAL is always 0.
  3. GPIO Output:
    • • When OUT_XOR is 0: OVAL value is output directly.
    • • When OUT_XOR is 1: OVAL value is inverted for output.
  4. GPIO Output Enable:
    • • When OE is 1: Output is enabled.
    • • When OE is 0: No output (Hi-Z).

3.2 Control of 7-Segment LED Specifications and Control Guidelines for TM1637

Documents: English versions are available below

https://github.com/revolunet/tm1637/blob/master/datasheet-en.pdf

Features:
  • • Communication is via 2 wires, CLK and DIO.
  • • DIO is bidirectional, necessitating collision avoidance.
  • • The datasheet lacks timing regulations for output off, making control methodologies unclear.

=> Open-drain control similar to I2C is assumed?

Controls like the gpio-i2c driver in Linux:
  • • For outputting a 1, disable output and use pull-up resistors for high.
  • • For outputting a 0, push-pull low output.

3.3. Method to Control TM1637 via GPIO

Set interfaces for OE control and output data on GPIO.

  1. Low Output:
    • • Set output data to 0.
    • • Enable output.
  2. High Output:
    • • Disable output.
    • → External pull-up will result in high output.

4. Operation of QSPI Flash in Dual/Quad mode

For this test:
  • • We used W25Q32JVSIQ which supports QPI mode and the QE bit is set to 1 by default.
  • • We used Fast Read in QPI mode.

4.1. Set SPI0 IO0-3 pins to bidirectional mode.

reg_mprj_io_13 = GPIO_MODE_USER_STD_BIDIRECTIONAL; // IO3 reg_mprj_io_12 = GPIO_MODE_USER_STD_BIDIRECTIONAL; // IO2 reg_mprj_io_11 = GPIO_MODE_USER_STD_BIDIRECTIONAL; // IO1 reg_mprj_io_10 = GPIO_MODE_USER_STD_BIDIRECTIONAL; // IO0

4.2. Set SPI Flash to Dual/Quad mode

  1. Configure the SPI Flash Instruction Format Register according to the QSPI Flash datasheet.

SPI Flash Instruction Format Register (ffmt)

Bits Field Name Attr. Rst. Description
0 cmd_en RW 0x1 Enable sending of command
[3:1] addr_len RW 0x3 Number of address bytes (0 to 4)
[7:4] pad_cnt RW 0x0 Number of dummy cycles
[9:8] cmd_proto RW 0x0 Protocol for transmitting command
[11:10] addr_proto RW 0x0 Protocol for transmitting address and padding
[13:12] data_proto RW 0x0 Protocol for receiving data bytes
[15:14] Reserved
[23:16] cmd_code RW 0x3 Value of command byte
[31:24] pad_code RW 0x0 First 8 bits to transmit during dummy cycles

For example, below code set the SPI Flash Instruction Format Register to use Fast Read in QPI mode:

// Set XIP access to Quad mode dummy = SPI_INSN_CMD_EN | SPI_INSN_ADDR_LEN(0x3) | SPI_INSN_PAD_CNT(0x2) | SPI_INSN_CMD_PROTO(SPI_PROTO_Q) | SPI_INSN_ADDR_PROTO(SPI_PROTO_Q) | SPI_INSN_DATA_PROTO(SPI_PROTO_Q) | SPI_INSN_CMD_CODE(0x0b) // Fast read | SPI_INSN_PAD_CODE(0x00); while (_REG32(spi_base_addr, SPI_REG_RFMT) != dummy) { _REG32(spi_base_addr, SPI_REG_RFMT) = dummy; }
  1. Send command to SPI Flash to switch it to work in QPI mode.
// Set SPI Flash to Quad mode while (_REG32(spi_base_addr, SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); // Wait until TX FIFO not full _REG32(spi_base_addr, SPI_REG_TXFIFO) = CMD_ENTER_QUAD_MODE; // 0x38

Note: This function needs to be executed on ITIM (Instruction Tightly Integrated Memory) instead of QSPI Flash.

__attribute__ ((section (".text_itim"))) void init_spi(uint32_t spi_base_addr) { volatile uint32_t dummy; asm volatile ("fence\n\t" "fence.i"); // Set SPI clock while (_REG32(spi_base_addr, SPI_REG_SCKDIV) != SCKDIV) { _REG32(spi_base_addr, SPI_REG_SCKDIV) = SCKDIV; } // Disable XIP mode while (_REG32(spi_base_addr, SPI_REG_RCTRL) != 0x0) { _REG32(spi_base_addr, SPI_REG_RCTRL) = 0x0; } // Set SPI Flash to Quad mode while (_REG32(spi_base_addr, SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); // Wait until TX FIFO not full _REG32(spi_base_addr, SPI_REG_TXFIFO) = CMD_ENTER_QUAD_MODE; // Set XIP access to Quad mode dummy = SPI_INSN_CMD_EN | SPI_INSN_ADDR_LEN(0x3) | SPI_INSN_PAD_CNT(0x2) | SPI_INSN_CMD_PROTO(SPI_PROTO_Q) | SPI_INSN_ADDR_PROTO(SPI_PROTO_Q) | SPI_INSN_DATA_PROTO(SPI_PROTO_Q) | SPI_INSN_CMD_CODE(0x0b) // Fast read | SPI_INSN_PAD_CODE(0x00); while (_REG32(spi_base_addr, SPI_REG_RFMT) != dummy) { _REG32(spi_base_addr, SPI_REG_RFMT) = dummy; } // Enable XIP mode while (_REG32(spi_base_addr, SPI_REG_RCTRL) != SPI_FCTRL_EN) { _REG32(spi_base_addr, SPI_REG_RCTRL) = SPI_FCTRL_EN; } }

4.3. Result

Below is the result that run the QSPI flash in QPI mode:

Quad mode