diff --git a/sdk/bsp/bsp.mk b/sdk/bsp/bsp.mk index bdd770f..b1323c1 100644 --- a/sdk/bsp/bsp.mk +++ b/sdk/bsp/bsp.mk @@ -22,7 +22,7 @@ C_SRCS += $(BSP_DIR)/lib/utils.c C_SRCS += $(BSP_DIR)/lib/xprintf.c C_SRCS += $(BSP_DIR)/lib/uart.c C_SRCS += $(BSP_DIR)/lib/sim_ctrl.c -C_SRCS += $(BSP_DIR)/lib/machine_timer.c +C_SRCS += $(BSP_DIR)/lib/timer.c C_SRCS += $(BSP_DIR)/lib/gpio.c C_SRCS += $(BSP_DIR)/lib/rvic.c diff --git a/sdk/bsp/include/timer.h b/sdk/bsp/include/timer.h index 9f9d0af..1e3cad6 100644 --- a/sdk/bsp/include/timer.h +++ b/sdk/bsp/include/timer.h @@ -1,11 +1,56 @@ -#ifndef _TIMER_H_ -#define _TIMER_H_ - -#define TIMER0_BASE (0x40000000) -#define TIMER0_CTRL (TIMER0_BASE + (0x00)) -#define TIMER0_COUNT (TIMER0_BASE + (0x04)) -#define TIMER0_VALUE (TIMER0_BASE + (0x08)) - -#define TIMER0_REG(addr) (*((volatile uint32_t *)addr)) - -#endif +// Generated register defines for timer + +// Copyright information found in source file: +// Copyright lowRISC contributors. + +// Licensing information found in source file: +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef _TIMER_REG_DEFS_ +#define _TIMER_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define TIMER_PARAM_REG_WIDTH 32 + +#define TIMER0_BASE_ADDR (0x40000000) +#define TIMER0_REG(offset) (*((volatile uint32_t *)(TIMER0_BASE_ADDR + offset))) + +// Timer control register +#define TIMER_CTRL_REG_OFFSET 0x0 +#define TIMER_CTRL_REG_RESVAL 0x0 +#define TIMER_CTRL_EN_BIT 0 +#define TIMER_CTRL_INT_EN_BIT 1 +#define TIMER_CTRL_INT_PENDING_BIT 2 +#define TIMER_CTRL_MODE_BIT 3 +#define TIMER_CTRL_CLK_DIV_MASK 0xffffff +#define TIMER_CTRL_CLK_DIV_OFFSET 8 +#define TIMER_CTRL_CLK_DIV_FIELD \ + ((bitfield_field32_t) { .mask = TIMER_CTRL_CLK_DIV_MASK, .index = TIMER_CTRL_CLK_DIV_OFFSET }) + +// Timer expired value register +#define TIMER_VALUE_REG_OFFSET 0x4 +#define TIMER_VALUE_REG_RESVAL 0x0 + +// Timer current count register +#define TIMER_COUNT_REG_OFFSET 0x8 +#define TIMER_COUNT_REG_RESVAL 0x0 + +void timer0_start(uint8_t en); +void timer0_set_value(uint32_t val); +void timer0_set_int_enable(uint8_t en); +void timer0_clear_int_pending(); +uint8_t timer0_get_int_pending(); +uint32_t timer0_get_current_count(); +void timer0_set_mode_auto_reload(); +void timer0_set_mode_ontshot(); +void timer0_set_div(uint32_t div); + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _TIMER_REG_DEFS_ +// End generated register defines for timer \ No newline at end of file diff --git a/sdk/bsp/lib/timer.c b/sdk/bsp/lib/timer.c new file mode 100644 index 0000000..ac60063 --- /dev/null +++ b/sdk/bsp/lib/timer.c @@ -0,0 +1,59 @@ +#include + +#include "../include/timer.h" + + +void timer0_start(uint8_t en) +{ + if (en) + TIMER0_REG(TIMER_CTRL_REG_OFFSET) |= 1 << TIMER_CTRL_EN_BIT; + else + TIMER0_REG(TIMER_CTRL_REG_OFFSET) &= ~(1 << TIMER_CTRL_EN_BIT); +} + +void timer0_set_value(uint32_t val) +{ + TIMER0_REG(TIMER_VALUE_REG_OFFSET) = val; +} + +void timer0_set_int_enable(uint8_t en) +{ + if (en) + TIMER0_REG(TIMER_CTRL_REG_OFFSET) |= 1 << TIMER_CTRL_INT_EN_BIT; + else + TIMER0_REG(TIMER_CTRL_REG_OFFSET) &= ~(1 << TIMER_CTRL_INT_EN_BIT); +} + +void timer0_clear_int_pending() +{ + TIMER0_REG(TIMER_CTRL_REG_OFFSET) |= 1 << TIMER_CTRL_INT_PENDING_BIT; +} + +uint8_t timer0_get_int_pending() +{ + if (TIMER0_REG(TIMER_CTRL_REG_OFFSET) & (1 << TIMER_CTRL_INT_PENDING_BIT)) + return 1; + else + return 0; +} + +uint32_t timer0_get_current_count() +{ + return TIMER0_REG(TIMER_COUNT_REG_OFFSET); +} + +void timer0_set_mode_auto_reload() +{ + TIMER0_REG(TIMER_CTRL_REG_OFFSET) |= 1 << TIMER_CTRL_MODE_BIT; +} + +void timer0_set_mode_ontshot() +{ + TIMER0_REG(TIMER_CTRL_REG_OFFSET) &= ~(1 << TIMER_CTRL_MODE_BIT); +} + +void timer0_set_div(uint32_t div) +{ + TIMER0_REG(TIMER_CTRL_REG_OFFSET) &= ~(TIMER_CTRL_CLK_DIV_MASK << TIMER_CTRL_CLK_DIV_OFFSET); + TIMER0_REG(TIMER_CTRL_REG_OFFSET) |= div << TIMER_CTRL_CLK_DIV_OFFSET; +} diff --git a/sdk/examples/timer/.gitignore b/sdk/examples/timer/.gitignore new file mode 100644 index 0000000..6cb4470 --- /dev/null +++ b/sdk/examples/timer/.gitignore @@ -0,0 +1,8 @@ +# Object files +*.o +*.ko +*.obj +*.bin +*.dump +*.mem +timer diff --git a/sdk/examples/timer/Makefile b/sdk/examples/timer/Makefile new file mode 100644 index 0000000..7a522ae --- /dev/null +++ b/sdk/examples/timer/Makefile @@ -0,0 +1,20 @@ +RISCV_ARCH := rv32im +RISCV_ABI := ilp32 +RISCV_MCMODEL := medlow + + +TARGET = timer + + +#CFLAGS += -DSIMULATION +#CFLAGS += -Os +#ASM_SRCS += +#LDFLAGS += +#INCLUDES += -I. + +C_SRCS := \ + main.c \ + + +BSP_DIR = ../../bsp +include ../../bsp/bsp.mk diff --git a/sdk/examples/timer/README.md b/sdk/examples/timer/README.md new file mode 100644 index 0000000..e51e6fb --- /dev/null +++ b/sdk/examples/timer/README.md @@ -0,0 +1 @@ +机器定时器(中断)例程。 \ No newline at end of file diff --git a/sdk/examples/timer/main.c b/sdk/examples/timer/main.c new file mode 100644 index 0000000..6fa3cd8 --- /dev/null +++ b/sdk/examples/timer/main.c @@ -0,0 +1,62 @@ +#include + +#include "../../bsp/include/timer.h" +#include "../../bsp/include/utils.h" +#include "../../bsp/include/rvic.h" +#include "../../bsp/include/gpio.h" + +static volatile uint32_t count; + +int main() +{ + count = 0; + +#ifdef SIMULATION + timer0_set_div(50); + timer0_set_value(100); // 100us period + timer0_clear_int_pending(); + timer0_set_int_enable(1); + timer0_set_mode_auto_reload(); + global_irq_enable(); + rvic_irq_enable(0); + timer0_start(1); + + while (1) { + if (count == 3) { + timer0_start(0); + // TODO: do something + set_test_pass(); + break; + } + } + + return 0; +#else + timer0_set_div(25); + timer0_set_value(10000); // 10ms period + timer0_clear_int_pending(); + timer0_set_int_enable(1); + timer0_set_mode_auto_reload(); + global_irq_enable(); + rvic_irq_enable(0); + timer0_start(1); + + gpio_output_enable(GPIO0); + + while (1) { + // 500ms + if (count == 50) { + count = 0; + gpio_data_toggle(GPIO0); // toggle led + } + } +#endif +} + +void timer_irq_handler() +{ + count++; + + timer0_clear_int_pending(); + rvic_clear_irq_pending(0); +}