[sw/lib] add simple busy-wait delay function

that do not rely on any specific CPU hardware
This commit is contained in:
stnolting 2025-02-17 20:54:32 +01:00
parent 9340394934
commit ece8380e4f
7 changed files with 106 additions and 18 deletions

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //
@ -15,6 +15,16 @@
#include <neorv32.h>
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* Main function; shows an incrementing 8-bit counter on GPIO.output(7:0).
*
@ -31,7 +41,7 @@ int main() {
while (1) {
neorv32_gpio_port_set(cnt++ & 0xFF); // increment counter and mask for lowest 8 bit
neorv32_cpu_delay_ms(250); // wait 250ms using busy wait
delay_ms(250); // wait 250ms using busy wait
}
// this should never be reached

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //
@ -33,6 +33,16 @@
uint32_t hsv2rgb(int h, int v);
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* Main function
* This demo uses a 12-LED RGB ring
@ -83,7 +93,7 @@ int main() {
for (i=0; i<NUM_LEDS_24BIT; i++) {
neorv32_neoled_write_blocking(0);
}
neorv32_cpu_delay_ms(500);
delay_ms(500);
// a simple animation example: rotating rainbow
@ -100,7 +110,7 @@ int main() {
angle += 1; // rotation increment per frame
neorv32_neoled_strobe_blocking(); // send strobe ("RESET") command
neorv32_cpu_delay_ms(10); // delay between frames
delay_ms(10); // delay between frames
}
return 0;

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //
@ -27,6 +27,15 @@
/**@}*/
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* This program generates a simple dimming sequence for PWM channels 0 to 3.
@ -115,7 +124,7 @@ int main() {
}
neorv32_pwm_ch_set_duty(ch, dc); // set new duty cycle for channel
neorv32_cpu_delay_ms(3); // wait ~3ms using busy-wait
delay_ms(3); // wait ~3ms using busy-wait
}
return 0;

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //
@ -33,6 +33,16 @@ void generate_histogram(void);
void compute_rate(void);
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* Simple true random number test/demo program.
*
@ -73,7 +83,7 @@ int main(void) {
neorv32_uart0_printf("\nTRNG FIFO depth: %i\n", neorv32_trng_get_fifo_depth());
neorv32_uart0_printf("Starting TRNG...\n");
neorv32_trng_enable();
neorv32_cpu_delay_ms(100); // TRNG "warm up"
delay_ms(100); // TRNG "warm up"
neorv32_trng_fifo_clear(); // discard "warm-up" data
while(1) {

View file

@ -26,6 +26,16 @@
/**@}*/
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* Main function
*
@ -91,7 +101,7 @@ int main() {
neorv32_uart0_puts("Resetting WDT 5 times...\n");
int i;
for (i=0; i<5; i++) {
neorv32_cpu_delay_ms(750);
delay_ms(750);
neorv32_wdt_feed(WDT_PASSWORD); // reset internal counter using the access password
neorv32_uart0_puts("WDT reset.\n");
}

View file

@ -1,7 +1,7 @@
// ================================================================================ //
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
// Copyright (c) NEORV32 contributors. //
// Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. //
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
// SPDX-License-Identifier: BSD-3-Clause //
// ================================================================================ //
@ -21,17 +21,17 @@
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
#define BAUD_RATE (19200)
/** Universe x size (has to be a multiple of 8) */
#define NUM_CELLS_X 160
#define NUM_CELLS_X (160)
/** Universe y size */
#define NUM_CELLS_Y 40
#define NUM_CELLS_Y (40)
/** Delay between generations in ms */
#define GEN_DELAY 500
#define GEN_DELAY (500)
/** Symbol for dead cell */
#define CELL_DEAD (' ')
#define CELL_DEAD (' ')
/** Symbol for alive cell */
#define CELL_ALIVE ('#')
#define CELL_ALIVE ('#')
/**@}*/
@ -50,6 +50,16 @@ void print_universe(int u);
int pop_count(int u);
/**********************************************************************//**
* Simple bus-wait helper.
*
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void delay_ms(uint32_t time_ms) {
neorv32_aux_delay_ms(neorv32_sysinfo_get_clk(), time_ms);
}
/**********************************************************************//**
* Conway's Game of Life.
*
@ -168,7 +178,7 @@ int main(void) {
generation++;
// wait GEN_DELAY ms
neorv32_cpu_delay_ms(GEN_DELAY);
delay_ms(GEN_DELAY);
}
}

View file

@ -14,6 +14,35 @@
#include <neorv32.h>
/**********************************************************************//**
* Simple delay function using busy-wait.
*
* @warning Timing is imprecise! Use CLINT.MTIME or CSR.[M]CYCLE[H] for precise timing.
*
* @param[in] clock_hz CPU clock speed in Hz.
* @param[in] time_ms Time in ms to wait (unsigned 32-bit).
**************************************************************************/
void neorv32_aux_delay_ms(uint32_t clock_hz, uint32_t time_ms) {
// clock ticks per ms (avoid division, therefore shift by 10 instead dividing by 1000)
uint32_t ms_ticks = clock_hz >> 10;
uint64_t wait_cycles = ((uint64_t)ms_ticks) * ((uint64_t)time_ms);
// divide by clock cycles per iteration of the ASM loop (16 = shift by 4)
uint32_t iterations = (uint32_t)(wait_cycles >> 4);
asm volatile (
" __neorv32_aux_delay_ms_start: \n"
" beq %[cnt_r], zero, __neorv32_aux_delay_ms_end \n" // 3 cycles (if not taken)
" bne zero, zero, __neorv32_aux_delay_ms_end \n" // 3 cycles (never taken)
" addi %[cnt_w], %[cnt_r], -1 \n" // 2 cycles
" nop \n" // 2 cycles
" j __neorv32_aux_delay_ms_start \n" // 6 cycles
" __neorv32_aux_delay_ms_end: \n"
: [cnt_w] "=r" (iterations) : [cnt_r] "r" (iterations)
);
}
/**********************************************************************//**
* Convert date to Unix time stamp.
*