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

cpu/fe310: several cleanup in implementation #12934

Merged
merged 8 commits into from
Jan 11, 2020
93 changes: 0 additions & 93 deletions boards/hifive1/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,104 +18,14 @@
* @}
*/

#include <stdio.h>
#include <errno.h>

#include "cpu.h"
#include "board.h"
#include "periph/gpio.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/prci_driver.h"

/*
* Configure the memory mapped flash for faster throughput
* to minimize interrupt latency on an I-Cache miss and refill
* from flash. Alternatively (and faster) the interrupt
* routine could be put in SRAM. The linker script supports
* code in SRAM using the ".hotcode" section.

* The flash chip on the HiFive1 is the ISSI 25LP128
* http://www.issi.com/WW/pdf/25LP128.pdf
* The maximum frequency it can run at is 133MHz in
* "Fast Read Dual I/O" mode.
* Note the updated data sheet:
* https://static.dev.sifive.com/SiFive-FE310-G000-datasheet-v1.0.4.pdf
* states "Address and write data using DQ[3] for transmission will not
* function properly." This rules out QPI for the XIP memory mapped flash.
* #define MAX_FLASH_FREQ 133000000
* On forum SiFive says "safe" operation would be 40MHz. 50MHz seems to work
* fine.
*/
#define MAX_FLASH_FREQ 50000000

/*
* CPU max is 320MHz+ according to datasheet but
* the relationship between cpu clock and spi clock is determined
* by SCKDIV. Given we're trying to achieve maximum I-cache refill
* for the flash we let MAX_FLASH_FREQ dictate the CPU clock.
*/
#define CPU_DESIRED_FREQ 200000000

/*
* The relationship between the input clock and SCK is given
* by the following formula (Fin is processor/tile-link clock):
* Fsck = Fin/(2(div + 1))
* FYI - For 320MHZ it seems to be tolerating a faster SPI clock (56MHz)
*/
#define SCKDIV ((CPU_DESIRED_FREQ - 1) / (MAX_FLASH_FREQ * 2))

/* This should work for any reasonable cpu clock value. */
#define SCKDIV_SAFE 3

/*
* By default the SPI initialized as:
* https://github.com/sifive/sifive-blocks/blob/master/src/main/scala/devices/spi/SPIFlash.scala
* insn.cmd.en := Bool(true)
* insn.cmd.code := Bits(0x03)
* insn.cmd.proto := SPIProtocol.Single
* insn.addr.len := UInt(3)
* insn.addr.proto := SPIProtocol.Single
* insn.pad.cnt := UInt(0)
* insn.pad.code := Bits(0)
* insn.data.proto := SPIProtocol.Single
*
* 25LP128 appears to left in post-reset default state. Boot code
* does not modify it. We change the SPI configuration here.
*/

void board_init_clock(void)
{
/* In case we are executing from QSPI, (which is quite likely) we need to
* set the QSPI clock divider appropriately before boosting the clock
* frequency. PRCI_set_hfrosctrim_for_f_cpu() tries multiple clocks
* so choose a safe value that should work for all frequencies.
*/
SPI0_REG(SPI_REG_SCKDIV) = SCKDIV_SAFE;

/* Note: The range is limited to ~100MHz and depends on PLL settings */
PRCI_set_hfrosctrim_for_f_cpu(CPU_DESIRED_FREQ, PRCI_FREQ_UNDERSHOOT);

/* begin{code-style-ignore} */
SPI0_REG(SPI_REG_FFMT) = /* setup "Fast Read Dual I/O" 1-1-2 */
SPI_INSN_CMD_EN | /* Enable memory-mapped flash */
SPI_INSN_ADDR_LEN(3) | /* 25LP128 read commands have 3 address bytes */
SPI_INSN_PAD_CNT(4) | /* 25LP128 Table 6.9 Read Dummy Cycles P4,P3=0,0 */
SPI_INSN_CMD_PROTO(SPI_PROTO_S) | /* 25LP128 Table 8.1 "Instruction */
SPI_INSN_ADDR_PROTO(SPI_PROTO_D) | /* Set" shows mode for cmd, addr, and */
SPI_INSN_DATA_PROTO(SPI_PROTO_D) | /* data protocol for given instruction */
SPI_INSN_CMD_CODE(0xbb) | /* Set the instruction to "Fast Read Dual I/O" */
SPI_INSN_PAD_CODE(0x00); /* Dummy cycle sends 0 value bits */
/* end{code-style-ignore} */

SPI0_REG(SPI_REG_SCKDIV) = SCKDIV;
}

void board_init(void)
{
/* Initialize CPU and clocks */
cpu_init();
board_init_clock();

/* Configure GPIOs for LEDs */
gpio_init(LED0_PIN, GPIO_OUT);
Expand All @@ -126,7 +36,4 @@ void board_init(void)
LED0_OFF;
LED1_OFF;
LED2_OFF;

/* Initialize newlib-nano library stubs */
nanostubs_init();
}
7 changes: 7 additions & 0 deletions boards/hifive1/include/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
extern "C" {
#endif

/**
* @name Xtimer configuration
* @{
*/
#define XTIMER_HZ (32768UL)
/** @} */

/**
* @name Macros for controlling the on-board LEDs
* @{
Expand Down
65 changes: 46 additions & 19 deletions boards/hifive1/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,53 @@ extern "C" {
* @name Core Clock configuration
* @{
*/
/* As defined in boards/hifive1/board.c CPU_DESIRED_FREQ **/
#define CLOCK_CORECLOCK (200000000ul)
/** @} */
#define USE_CLOCK_HFXOSC_PLL (1)
#define USE_CLOCK_HFXOSC (0)
#define USE_CLOCK_HFROSC_PLL (0)

/**
* @name Xtimer configuration
* @{
*/
#define XTIMER_DEV (0)
#define XTIMER_CHAN (0)
#define XTIMER_WIDTH (32)
#define XTIMER_HZ (32768ul)
#if USE_CLOCK_HFROSC_PLL && (USE_CLOCK_HFXOSC_PLL || USE_CLOCK_HFXOSC)
#error "Cannot use HFROSC_PLL with HFXOSC based configurations"
#endif

#if USE_CLOCK_HFXOSC_PLL && USE_CLOCK_HFXOSC
#error "Cannot use HFXOSC with HFXOSC_PLL"
#endif

#if USE_CLOCK_HFXOSC_PLL
#define CLOCK_PLL_R (1) /* Divide input clock by 2, mandatory with HFXOSC */
#define CLOCK_PLL_F (39) /* Multiply REFR by 80, e.g 2 * (39 + 1) */
#define CLOCK_PLL_Q (1) /* Divide VCO by 2, e.g 2^1 */
#define CLOCK_PLL_INPUT_CLOCK (16000000UL)
#define CLOCK_PLL_REFR (CLOCK_PLL_INPUT_CLOCK / (CLOCK_PLL_R + 1))
#define CLOCK_PLL_VCO (CLOCK_PLL_REFR * (2 * (CLOCK_PLL_F + 1)))
#define CLOCK_PLL_OUT (CLOCK_PLL_VCO / (1 << CLOCK_PLL_Q))
#define CLOCK_CORECLOCK (CLOCK_PLL_OUT) /* 320000000Hz with the values used above */

/* Check PLL settings */
#if CLOCK_PLL_REFR != 8000000
#error "Only R=2 can be used when using HFXOSC"
#endif
#if (CLOCK_PLL_VCO < 384000000) || (CLOCK_PLL_VCO > 768000000)
#error "VCO frequency must be in the range [384MHz - 768MHz], check the CLOCK_PLL_F value"
#endif
#if (CLOCK_PLL_OUT < 48000000) || (CLOCK_PLL_OUT > 384000000)
#error "PLL output frequency must be in the range [48MHz - 384MHz], check the CLOCK_PLL_Q value"
#endif

#elif USE_CLOCK_HFXOSC
#define CLOCK_CORECLOCK (16000000UL)

/*
When using HFROSC input clock, the core clock cannot be computed from settings,
call cpu_freq() to get the configured CPU frequency.
*/
#elif USE_CLOCK_HFROSC_PLL
#define CLOCK_DESIRED_FREQUENCY (320000000UL)

#else
#define CLOCK_HFROSC_TRIM (6) /* ~72000000Hz input freq */
#define CLOCK_HFROSC_DIV (1) /* Divide by 2 */
#endif
/** @} */

/**
Expand Down Expand Up @@ -85,14 +120,6 @@ static const uart_conf_t uart_config[] = {

/** @} */

/**
* @name GPIO configuration
*
* @{
*/
#define GPIO_INTR_PRIORITY (3)
/** @} */

/**
* @name PWM configuration
*
Expand Down
115 changes: 0 additions & 115 deletions boards/hifive1b/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,126 +18,14 @@
* @}
*/

#include <stdio.h>
#include <errno.h>

#include "cpu.h"
#include "board.h"
#include "periph/gpio.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/prci_driver.h"

/*
* Configure the memory mapped flash for faster throughput
* to minimize interrupt latency on an I-Cache miss and refill
* from flash. Alternatively (and faster) the interrupt
* routine could be put in SRAM.

* The flash chip on the HiFive1b is the ISSI 25LP03D
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to keep this reference somewhere.

* http://www.issi.com/WW/pdf/25LP-WP032D.pdf
* The maximum frequency it can run at is 115MHz in
* "Fast Read Dual I/O" mode.
* #define MAX_FLASH_FREQ 115000000
*
* FYI - Like the FE310-G000, the G002 has problems with reading flash
* faster than 50MHz
*/
#define MAX_FLASH_FREQ 50000000

/*
* CPU max is 320MHz+ according to datasheet but
* the relationship between cpu clock and spi clock is determined
* by SCKDIV. Given we're trying to achieve maximum I-cache refill
* for the flash we let MAX_FLASH_FREQ dictate the CPU clock.
*/
#define CPU_DESIRED_FREQ 320000000

/*
* The relationship between the input clock and SCK is given
* by the following formula (Fin is processor/tile-link clock):
* Fsck = Fin/(2(div + 1))
*/
#define SCKDIV ((CPU_DESIRED_FREQ - 1) / (MAX_FLASH_FREQ * 2))

/* This should work for any reasonable cpu clock value. */
#define SCKDIV_SAFE 3

/*
* By default the SPI FFMT initialized as:
* cmd_en = 1
* addr_len = 3
* cmd_code = 3
* all other fields = 0
*/

void board_init_clock(void)
{
/* In case we are executing from QSPI, (which is quite likely) we need to
* set the QSPI clock divider appropriately before boosting the clock
* frequency. PRCI_set_hfrosctrim_for_f_cpu() tries multiple clocks
* so choose a safe value that should work for all frequencies.
*/
SPI0_REG(SPI_REG_SCKDIV) = SCKDIV_SAFE;

/* Note: The range is limited to ~100MHz and depends on PLL settings */
PRCI_set_hfrosctrim_for_f_cpu(CPU_DESIRED_FREQ, PRCI_FREQ_UNDERSHOOT);

/* begin{code-style-ignore} */
SPI0_REG(SPI_REG_FFMT) = /* setup "Fast Read Dual I/O" */
SPI_INSN_CMD_EN | /* Enable memory-mapped flash */
SPI_INSN_ADDR_LEN(3) | /* 25LP03D read commands have 3 address bytes */
SPI_INSN_PAD_CNT(4) | /* 25LP03D Table 6.11 Read Dummy Cycles = 4 */
SPI_INSN_CMD_PROTO(SPI_PROTO_S) | /* 25LP03D Table 8.1 "Instruction */
SPI_INSN_ADDR_PROTO(SPI_PROTO_D) | /* Set" shows mode for cmd, addr, and */
SPI_INSN_DATA_PROTO(SPI_PROTO_D) | /* data protocol for given instruction */
SPI_INSN_CMD_CODE(0xBB) | /* Set the instruction to "Fast Read Dual I/O" */
SPI_INSN_PAD_CODE(0x00); /* Dummy cycle sends 0 value bits */
/* end{code-style-ignore} */

SPI0_REG(SPI_REG_SCKDIV) = SCKDIV;
}

__attribute__ ((section (".ramfunc")))
void board_init_flash(void)
{
/* Update the QSPI interface to adjust to the CPU speed
* This function needs to execute from the RAM
* when the QSPI interface is being reconfigured because the flash
* can't be accessed during this time
*/

/* Disable SPI flash mode */
SPI0_REG(SPI_REG_FCTRL) &= ~SPI_FCTRL_EN;

/* Enable QPI mode by sending command to flash */
SPI0_REG(SPI_REG_TXFIFO) = 0x35;

/* begin{code-style-ignore} */
SPI0_REG(SPI_REG_FFMT) = /* setup "Fast Read Quad I/O (QPI mode)" */
SPI_INSN_CMD_EN | /* Enable memory-mapped flash */
SPI_INSN_ADDR_LEN(3) | /* 25LP03D read commands have 3 address bytes */
SPI_INSN_PAD_CNT(6) | /* 25LP03D Table 6.11 Read Dummy Cycles = 6 */
SPI_INSN_CMD_PROTO(SPI_PROTO_Q) | /* 25LP03D Table 8.1 "Instruction */
SPI_INSN_ADDR_PROTO(SPI_PROTO_Q) | /* Set" shows mode for cmd, addr, and */
SPI_INSN_DATA_PROTO(SPI_PROTO_Q) | /* data protocol for given instruction */
SPI_INSN_CMD_CODE(0xEB) | /* Set the instruction to "Fast Read Quad I/O" */
SPI_INSN_PAD_CODE(0x00); /* Dummy cycle sends 0 value bits */
/* end{code-style-ignore} */

/* Re-enable SPI flash mode */
SPI0_REG(SPI_REG_FCTRL) |= SPI_FCTRL_EN;

/* Adjust the SPI clk divider for to boost flash speed */
// SPI0_REG(SPI_REG_SCKDIV) = SCKDIV;
}

void board_init(void)
{
/* Initialize CPU and clocks */
cpu_init();
board_init_clock();
// board_init_flash();

/* Configure GPIOs for LEDs */
gpio_init(LED0_PIN, GPIO_OUT);
Expand All @@ -148,7 +36,4 @@ void board_init(void)
LED0_OFF;
LED1_OFF;
LED2_OFF;

/* Initialize newlib-nano library stubs */
nanostubs_init();
}
7 changes: 7 additions & 0 deletions boards/hifive1b/include/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
extern "C" {
#endif

/**
* @name Xtimer configuration
* @{
*/
#define XTIMER_HZ (32768UL)
/** @} */

/**
* @name Macros for controlling the on-board LEDs
* @{
Expand Down
Loading