risc-v/bl808: Add timer driver

This change implements a driver for the hardware timer blocks on the BL808, as well as a config with the timer example enabled.
This commit is contained in:
Henry Rovner 2024-07-18 07:19:39 -07:00 committed by Xiang Xiao
parent 42c9a829da
commit 049a6da098
11 changed files with 814 additions and 4 deletions

View file

@ -150,3 +150,9 @@ spi
This configuration enables support for SPI0 and spitool. This configuration enables support for SPI0 and spitool.
By default, GPIO14 is MISO, 13 is MOSI, 15 is SCLK and 12 is SS. By default, GPIO14 is MISO, 13 is MOSI, 15 is SCLK and 12 is SS.
Serial Console is enabled on UART3 at 2 Mbps. Serial Console is enabled on UART3 at 2 Mbps.
timer
-----
This configuration enables support for hardware timers and the timer example app.
Serial Console is enabled on UART3 at 2 Mbps.

View file

@ -52,7 +52,7 @@ I2C No
I2S No I2S No
PWM No PWM No
SPI Yes SPI Yes
Timers No Timers Yes
UART Yes UART Yes
USB No USB No
=========== ======= ==================== =========== ======= ====================

View file

@ -54,6 +54,8 @@
#define BL808_IRQ_UART3 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 4) #define BL808_IRQ_UART3 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 4)
#define BL808_IRQ_SPI1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 7) #define BL808_IRQ_SPI1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 7)
#define BL808_IRQ_D0_IPC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 38) #define BL808_IRQ_D0_IPC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 38)
#define BL808_IRQ_TIMER1_CH0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 61)
#define BL808_IRQ_TIMER1_CH1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 62)
#define BL808_IRQ_M0IC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 65) #define BL808_IRQ_M0IC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 65)
/* M0 IRQs ******************************************************************/ /* M0 IRQs ******************************************************************/
@ -63,5 +65,7 @@
#define BL808_IRQ_UART0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 28) #define BL808_IRQ_UART0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 28)
#define BL808_IRQ_UART1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 29) #define BL808_IRQ_UART1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 29)
#define BL808_IRQ_UART2 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 30) #define BL808_IRQ_UART2 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 30)
#define BL808_IRQ_TIMER0_CH0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 36)
#define BL808_IRQ_TIMER0_CH1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 37)
#endif /* __ARCH_RISCV_INCLUDE_BL808_IRQ_H */ #endif /* __ARCH_RISCV_INCLUDE_BL808_IRQ_H */

View file

@ -224,4 +224,9 @@ config BL808_SPI1_SS
endif endif
config BL808_TIMERS
bool "Timers"
default n
select TIMER
endmenu endmenu

View file

@ -28,4 +28,4 @@ HEAD_ASRC = bl808_head.S
CHIP_CSRCS = bl808_start.c bl808_irq_dispatch.c bl808_irq.c CHIP_CSRCS = bl808_start.c bl808_irq_dispatch.c bl808_irq.c
CHIP_CSRCS += bl808_timerisr.c bl808_allocateheap.c CHIP_CSRCS += bl808_timerisr.c bl808_allocateheap.c
CHIP_CSRCS += bl808_gpio.c bl808_mm_init.c bl808_pgalloc.c bl808_serial.c CHIP_CSRCS += bl808_gpio.c bl808_mm_init.c bl808_pgalloc.c bl808_serial.c
CHIP_CSRCS += bl808_gpadc.c bl808_spi.c CHIP_CSRCS += bl808_gpadc.c bl808_spi.c bl808_timer.c

View file

@ -0,0 +1,549 @@
/****************************************************************************
* arch/risc-v/src/bl808/bl808_timer.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/timers/timer.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/serial/tioctl.h>
#include "hardware/bl808_timer.h"
#include "riscv_internal.h"
#include "chip.h"
#include "bl808_timer.h"
#ifdef CONFIG_BL808_TIMERS
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define TIMER_GET_BLK(n) (n >= 2)
#define TIMER_GET_CH(n) (n % 2)
#define TIMER_CLK_SRC_XTAL 3
#define TIMER_CLK_SRC_NONE 5
#define XCLK_DIV 39 /* XCLK is 40 MHz, so divide by 40 */
/****************************************************************************
* Private Types
****************************************************************************/
enum bl808_timer_ch_e
{
TIMER0_CH0 = 0,
TIMER0_CH1 = 1,
TIMER1_CH0 = 2,
TIMER1_CH1 = 3
};
struct bl808_timer_ch_s
{
const struct timer_ops_s *ops;
enum bl808_timer_ch_e blk_ch;
tccb_t callback;
void *arg;
bool started;
uint32_t timeout;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
int bl808_timer_start(FAR struct timer_lowerhalf_s *lower);
int bl808_timer_stop(FAR struct timer_lowerhalf_s *lower);
int bl808_timer_getstatus(FAR struct timer_lowerhalf_s *lower,
FAR struct timer_status_s *status);
int bl808_timer_settimeout(FAR struct timer_lowerhalf_s *lower,
uint32_t timeout);
void bl808_timer_setcallback(FAR struct timer_lowerhalf_s *lower,
CODE tccb_t callback, FAR void *arg);
int bl808_timer_ioctl(FAR struct timer_lowerhalf_s *lower,
int cmd, unsigned long arg);
int bl808_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower,
FAR uint32_t *maxtimeout);
/****************************************************************************
* Private Data
****************************************************************************/
static struct timer_ops_s bl808_timer_ops =
{
.start = bl808_timer_start,
.stop = bl808_timer_stop,
.getstatus = bl808_timer_getstatus,
.settimeout = bl808_timer_settimeout,
.setcallback = bl808_timer_setcallback,
.ioctl = bl808_timer_ioctl,
.maxtimeout = bl808_timer_maxtimeout
};
static struct bl808_timer_ch_s timer0_ch0 =
{
.ops = &bl808_timer_ops,
.blk_ch = TIMER0_CH0,
.callback = NULL,
.arg = NULL,
.started = false,
.timeout = 0
};
static struct bl808_timer_ch_s timer0_ch1 =
{
.ops = &bl808_timer_ops,
.blk_ch = TIMER0_CH1,
.callback = NULL,
.arg = NULL,
.started = false,
.timeout = 0
};
static struct bl808_timer_ch_s timer1_ch0 =
{
.ops = &bl808_timer_ops,
.blk_ch = TIMER1_CH0,
.callback = NULL,
.arg = NULL,
.started = false,
.timeout = 0
};
static struct bl808_timer_ch_s timer1_ch1 =
{
.ops = &bl808_timer_ops,
.blk_ch = TIMER1_CH1,
.callback = NULL,
.arg = NULL,
.started = false,
.timeout = 0
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: timer_interrupt
*
* Description:
* Timer interrupt handler. Clears the interrupt and
* Calls the attached callback if there is one.
*
****************************************************************************/
static int __timer_interrupt(int irq, void *context, void *arg)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)arg;
uint32_t next_interval = 0;
/* Clear IRQ */
switch (irq)
{
case BL808_IRQ_TIMER0_CH0:
modifyreg32(BL808_TIMER_CH0_ICLR(0), 0, TIMER_COMP0_INT);
break;
case BL808_IRQ_TIMER0_CH1:
modifyreg32(BL808_TIMER_CH1_ICLR(0), 0, TIMER_COMP0_INT);
break;
case BL808_IRQ_TIMER1_CH0:
modifyreg32(BL808_TIMER_CH0_ICLR(1), 0, TIMER_COMP0_INT);
break;
case BL808_IRQ_TIMER1_CH1:
modifyreg32(BL808_TIMER_CH1_ICLR(1), 0, TIMER_COMP0_INT);
break;
default:
return -EIO;
}
if (priv->callback != NULL)
{
if (priv->callback(&next_interval, priv->arg))
{
if (next_interval > 0)
{
bl808_timer_settimeout((struct timer_lowerhalf_s *)priv,
next_interval);
}
bl808_timer_start((struct timer_lowerhalf_s *)priv);
}
}
return OK;
}
/****************************************************************************
* Name: bl808_timer_start
*
* Description:
* Reset the time to the current timeout and start the timer.
*
****************************************************************************/
int bl808_timer_start(FAR struct timer_lowerhalf_s *lower)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower;
if (TIMER_GET_CH(priv->blk_ch) == 0)
{
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_XTAL << TIMER_CH0_CLKSEL_SHIFT);
/* Clear timer */
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
0, TIMER_CH0_CLR);
/* Wait for the counter to clear */
while (getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch)))
!= 0);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLR, 0);
}
else /* Channel 1 */
{
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH1_CLKSEL_MASK,
TIMER_CLK_SRC_XTAL << TIMER_CH1_CLKSEL_SHIFT);
/* Clear timer */
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
0, TIMER_CH1_CLR);
/* Wait for the counter to clear */
while (getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch)))
!= 0);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH1_CLR, 0);
}
priv->started = true;
return OK;
}
/****************************************************************************
* Name: bl808_timer_stop
*
* Description:
* Stop the timer.
*
****************************************************************************/
int bl808_timer_stop(FAR struct timer_lowerhalf_s *lower)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower;
/* Timers are stopped by setting the input clock to NONE.
* This is done to allow calling timer_stop and then get
* the time left to timeout afterwards. If we used the
* timer enable bits, the counter would reset to 0 when stopped.
*/
if (TIMER_GET_CH(priv->blk_ch) == 0)
{
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT);
}
else
{
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT);
}
priv->started = false;
return OK;
}
/****************************************************************************
* Name: bl808_timer_getstatus
*
* Description:
* Get current timer status. Returns to status parameter.
*
****************************************************************************/
int bl808_timer_getstatus(FAR struct timer_lowerhalf_s *lower,
FAR struct timer_status_s *status)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower;
uint32_t current_count;
status->flags = priv->started
| ((priv->callback != NULL) << 1);
status->timeout = priv->timeout;
if (TIMER_GET_CH(priv->blk_ch) == 0)
{
current_count =
getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch)));
}
else
{
current_count =
getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch)));
}
status->timeleft = priv->timeout - current_count;
return OK;
}
/****************************************************************************
* Name: bl808_timer_settimeout
*
* Description:
* Set a new timeout value and reset the timer.
*
****************************************************************************/
int bl808_timer_settimeout(FAR struct timer_lowerhalf_s *lower,
uint32_t timeout)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower;
if (TIMER_GET_CH(priv->blk_ch) == 0)
{
modifyreg32(BL808_TIMER_CH0_COMP0(TIMER_GET_BLK(priv->blk_ch)),
0xffffffff, timeout);
priv->timeout = timeout;
/* Clock is needed to clear counters */
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_XTAL << TIMER_CH0_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
0, TIMER_CH0_CLR);
while (getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch)))
!= 0);
/* Disable clock to stop timer from running after clear */
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH0_CLR, 0);
}
else
{
modifyreg32(BL808_TIMER_CH1_COMP0(TIMER_GET_BLK(priv->blk_ch)),
0xffffffff, timeout);
priv->timeout = timeout;
/* Clock is needed to clear counters */
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH1_CLKSEL_MASK,
TIMER_CLK_SRC_XTAL << TIMER_CH1_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
0, TIMER_CH1_CLR);
while (getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch)))
!= 0);
/* Disable clock to stop timer from running after clear */
modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH1_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)),
TIMER_CH1_CLR, 0);
}
return OK;
}
/****************************************************************************
* Name: bl808_timer_setcallback
*
* Description:
* Sets a new callback to be run on timeout.
*
****************************************************************************/
void bl808_timer_setcallback(FAR struct timer_lowerhalf_s *lower,
CODE tccb_t callback, FAR void *arg)
{
struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower;
priv->callback = callback;
priv->arg = arg;
}
/****************************************************************************
* Name: bl808_timer_ioctl
*
* Description:
* Handle ioctl commands not recognized by upper-half.
*
****************************************************************************/
int bl808_timer_ioctl(FAR struct timer_lowerhalf_s *lower,
int cmd, unsigned long arg)
{
/* No additional ioctl commands implemented */
return -EIO;
}
/****************************************************************************
* Name: bl808_timer_maxtimeout
*
* Description:
* Return the maximum allowed timeout value.
* Returns to maxtimeout parameter.
*
****************************************************************************/
int bl808_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower,
FAR uint32_t *maxtimeout)
{
/* Timer comparators are 32-bit */
*maxtimeout = 0xffffffff;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int bl808_timer_init(void)
{
int ret = OK;
/* The registered devpaths follow the recommended naming
* convention, i.e. timer0, timer1, etc. The order chosen
* for the numbering is the same as for bl808_timer_ch_e.
*/
/* Timer 0, channel 0 */
modifyreg32(BL808_TIMER_TCCR(0), TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_CH0_IE(0), 0, TIMER_COMP0_INT);
modifyreg32(BL808_TIMER_DIV(0), TIMER_CH0_DIV_MASK,
(XCLK_DIV << TIMER_CH0_DIV_SHIFT));
modifyreg32(BL808_TIMER_MODE(0), 0, TIMER_CH0_MODE);
modifyreg32(BL808_TIMER_EN_CLR(0), 0, TIMER_CH0_EN);
ret |= irq_attach(BL808_IRQ_TIMER0_CH0, __timer_interrupt,
(void *)&timer0_ch0);
if (ret == OK)
{
up_enable_irq(BL808_IRQ_TIMER0_CH0);
}
timer_register("/dev/timer0",
(struct timer_lowerhalf_s *)&timer0_ch0);
/* Timer 0, channel 1 */
modifyreg32(BL808_TIMER_TCCR(0), TIMER_CH1_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_CH1_IE(0), 0, TIMER_COMP0_INT);
modifyreg32(BL808_TIMER_DIV(0), TIMER_CH1_DIV_MASK,
(XCLK_DIV << TIMER_CH1_DIV_SHIFT));
modifyreg32(BL808_TIMER_MODE(0), 0, TIMER_CH1_MODE);
modifyreg32(BL808_TIMER_EN_CLR(0), 0, TIMER_CH1_EN);
ret |= irq_attach(BL808_IRQ_TIMER0_CH1, __timer_interrupt,
(void *)&timer0_ch1);
if (ret == OK)
{
up_enable_irq(BL808_IRQ_TIMER0_CH1);
}
timer_register("/dev/timer1",
(struct timer_lowerhalf_s *)&timer0_ch1);
/* Timer 1, channel 0 */
modifyreg32(BL808_TIMER_TCCR(1), TIMER_CH0_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_CH0_IE(1), 0, TIMER_COMP0_INT);
modifyreg32(BL808_TIMER_DIV(1), TIMER_CH0_DIV_MASK,
(XCLK_DIV << TIMER_CH0_DIV_SHIFT));
modifyreg32(BL808_TIMER_MODE(1), 0, TIMER_CH0_MODE);
modifyreg32(BL808_TIMER_EN_CLR(1), 0, TIMER_CH0_EN);
ret |= irq_attach(BL808_IRQ_TIMER1_CH0, __timer_interrupt,
(void *)&timer1_ch0);
if (ret == OK)
{
up_enable_irq(BL808_IRQ_TIMER1_CH0);
}
timer_register("/dev/timer2",
(struct timer_lowerhalf_s *)&timer1_ch0);
/* Timer 1, channel 1 */
modifyreg32(BL808_TIMER_TCCR(1), TIMER_CH1_CLKSEL_MASK,
TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT);
modifyreg32(BL808_TIMER_CH1_IE(1), 0, TIMER_COMP0_INT);
modifyreg32(BL808_TIMER_DIV(1), TIMER_CH1_DIV_MASK,
(XCLK_DIV << TIMER_CH1_DIV_SHIFT));
modifyreg32(BL808_TIMER_MODE(1), 0, TIMER_CH1_MODE);
modifyreg32(BL808_TIMER_EN_CLR(1), 0, TIMER_CH1_EN);
ret |= irq_attach(BL808_IRQ_TIMER1_CH1, __timer_interrupt,
(void *)&timer1_ch1);
if (ret == OK)
{
up_enable_irq(BL808_IRQ_TIMER1_CH1);
}
timer_register("/dev/timer3",
(struct timer_lowerhalf_s *)&timer1_ch1);
return ret;
}
#endif /* CONFIG_BL808_TIMERS */

View file

@ -0,0 +1,39 @@
/****************************************************************************
* arch/risc-v/src/bl808/bl808_timer.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISC_V_SRC_BL808_BL808_TIMER_H
#define __ARCH_RISC_V_SRC_BL808_BL808_TIMER_H
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/****************************************************************************
* Name: bl808_timer_init
*
* Description:
* Initialize timer hardware and register character drivers
* for enabled timer channels.
*
****************************************************************************/
int bl808_timer_init(void);
#endif /* __ARCH_RISC_V_SRC_BL808_BL808_TIMER_H */

View file

@ -34,11 +34,13 @@
#define BL808_UART0_BASE 0x2000a000ul #define BL808_UART0_BASE 0x2000a000ul
#define BL808_UART1_BASE 0x2000a100ul #define BL808_UART1_BASE 0x2000a100ul
#define BL808_SPI0_BASE 0x2000a200ul #define BL808_SPI0_BASE 0x2000a200ul
#define BL808_TIMER0_BASE 0x2000a500ul
#define BL808_UART2_BASE 0x2000aa00ul #define BL808_UART2_BASE 0x2000aa00ul
#define BL808_AON_BASE 0x2000f000ul #define BL808_AON_BASE 0x2000f000ul
#define BL808_UART3_BASE 0x30002000ul #define BL808_UART3_BASE 0x30002000ul
#define BL808_MM_GLB_BASE 0x30007000ul #define BL808_MM_GLB_BASE 0x30007000ul
#define BL808_SPI1_BASE 0x30008000ul #define BL808_SPI1_BASE 0x30008000ul
#define BL808_TIMER1_BASE 0x30009000ul
#define BL808_PLIC_BASE 0xe0000000ul #define BL808_PLIC_BASE 0xe0000000ul
#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H */ #endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H */

View file

@ -0,0 +1,100 @@
/****************************************************************************
* arch/risc-v/src/bl808/hardware/bl808_timer.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H
#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "bl808_memorymap.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BL808_TIMER_BASE(n) ((n == 0) ? BL808_TIMER0_BASE \
: BL808_TIMER1_BASE)
/* Register offsets *********************************************************/
#define BL808_TIMER_TCCR_OFFSET 0x00
#define BL808_TIMER_CH0_COMP0_OFFSET 0x10
#define BL808_TIMER_CH1_COMP0_OFFSET 0x1c
#define BL808_TIMER_CH0_COUNTER_OFFSET 0x2c
#define BL808_TIMER_CH1_COUNTER_OFFSET 0x30
#define BL808_TIMER_CH0_IE_OFFSET 0x44
#define BL808_TIMER_CH1_IE_OFFSET 0x48
#define BL808_TIMER_CH0_ICLR_OFFSET 0x78
#define BL808_TIMER_CH1_ICLR_OFFSET 0x7c
#define BL808_TIMER_EN_CLR_OFFSET 0x84
#define BL808_TIMER_MODE_OFFSET 0x88
#define BL808_TIMER_DIV_OFFSET 0xBC
/* Register definitions *****************************************************/
#define BL808_TIMER_TCCR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_TCCR_OFFSET)
#define BL808_TIMER_CH0_COMP0(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_COMP0_OFFSET)
#define BL808_TIMER_CH1_COMP0(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_COMP0_OFFSET)
#define BL808_TIMER_CH0_COUNTER(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_COUNTER_OFFSET)
#define BL808_TIMER_CH1_COUNTER(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_COUNTER_OFFSET)
#define BL808_TIMER_CH0_IE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_IE_OFFSET)
#define BL808_TIMER_CH1_IE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_IE_OFFSET)
#define BL808_TIMER_CH0_ICLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_ICLR_OFFSET)
#define BL808_TIMER_CH1_ICLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_ICLR_OFFSET)
#define BL808_TIMER_EN_CLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_EN_CLR_OFFSET)
#define BL808_TIMER_MODE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_MODE_OFFSET)
#define BL808_TIMER_DIV(n) (BL808_TIMER_BASE(n) + BL808_TIMER_DIV_OFFSET)
/* Register bit definitions *************************************************/
/* TIMER_TCCR */
#define TIMER_CH0_CLKSEL_SHIFT (0)
#define TIMER_CH0_CLKSEL_MASK (0xf << TIMER_CH0_CLKSEL_SHIFT)
#define TIMER_CH1_CLKSEL_SHIFT (4)
#define TIMER_CH1_CLKSEL_MASK (0xf << TIMER_CH1_CLKSEL_SHIFT)
/* TIMER_CH(0/1)_I(E/CLR) */
#define TIMER_COMP0_INT (1 << 0)
/* TIMER_EN_CLR */
#define TIMER_CH0_EN (1 << 1)
#define TIMER_CH1_EN (1 << 2)
#define TIMER_CH0_CLR (1 << 5)
#define TIMER_CH1_CLR (1 << 6)
/* TIMER_MODE */
#define TIMER_CH0_MODE (1 << 1)
#define TIMER_CH1_MODE (1 << 2)
/* TIMER_DIV */
#define TIMER_CH0_DIV_SHIFT (8)
#define TIMER_CH0_DIV_MASK (0xff << TIMER_CH0_DIV_SHIFT)
#define TIMER_CH1_DIV_SHIFT (16)
#define TIMER_CH1_DIV_MASK (0xff << TIMER_CH1_DIV_SHIFT)
#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H */

View file

@ -0,0 +1,100 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DISABLE_OS_API is not set
# CONFIG_NSH_DISABLE_LOSMART is not set
# CONFIG_STANDARD_SERIAL is not set
CONFIG_ARCH="risc-v"
CONFIG_ARCH_ADDRENV=y
CONFIG_ARCH_BOARD="ox64"
CONFIG_ARCH_BOARD_BL808_OX64=y
CONFIG_ARCH_CHIP="bl808"
CONFIG_ARCH_CHIP_BL808=y
CONFIG_ARCH_DATA_NPAGES=128
CONFIG_ARCH_DATA_VBASE=0x80100000
CONFIG_ARCH_HEAP_NPAGES=128
CONFIG_ARCH_HEAP_VBASE=0x80200000
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_KERNEL_STACKSIZE=3072
CONFIG_ARCH_PGPOOL_MAPPING=y
CONFIG_ARCH_PGPOOL_PBASE=0x50600000
CONFIG_ARCH_PGPOOL_SIZE=4194304
CONFIG_ARCH_PGPOOL_VBASE=0x50600000
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_TEXT_NPAGES=128
CONFIG_ARCH_TEXT_VBASE=0x80000000
CONFIG_ARCH_USE_MMU=y
CONFIG_ARCH_USE_MPU=y
CONFIG_ARCH_USE_S_MODE=y
CONFIG_BL808_TIMERS=y
CONFIG_BL808_UART0=y
CONFIG_BL808_UART1=y
CONFIG_BL808_UART2=y
CONFIG_BL808_UART3=y
CONFIG_BOARDCTL_ROMDISK=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=1120
CONFIG_BUILD_KERNEL=y
CONFIG_DEBUG_ASSERTIONS=y
CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEV_ZERO=y
CONFIG_ELF=y
CONFIG_EXAMPLES_HELLO=m
CONFIG_EXAMPLES_TIMER=y
CONFIG_FS_PROCFS=y
CONFIG_FS_ROMFS=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INIT_FILEPATH="/system/bin/init"
CONFIG_INIT_MOUNT=y
CONFIG_INIT_MOUNT_FLAGS=0x1
CONFIG_INIT_MOUNT_TARGET="/system/bin"
CONFIG_INIT_STACKSIZE=3072
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_ENVPATH=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_PERROR_STDOUT=y
CONFIG_LIBC_STRERROR=y
CONFIG_MEMSET_64BIT=y
CONFIG_MEMSET_OPTSPEED=y
CONFIG_MM_PGALLOC=y
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_FILE_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_PATH_INITIAL="/system/bin"
CONFIG_RAM_SIZE=1048576
CONFIG_RAM_START=0x50200000
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_STACK_COLORATION=y
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2021
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_OSTEST=y
CONFIG_UART0_BAUD=2000000
CONFIG_UART0_BITS=7
CONFIG_UART1_BAUD=2000000
CONFIG_UART1_BITS=7
CONFIG_UART2_BAUD=2000000
CONFIG_UART2_BITS=7
CONFIG_UART3_BAUD=2000000
CONFIG_UART3_BITS=7
CONFIG_UART3_SERIAL_CONSOLE=y
CONFIG_USEC_PER_TICK=1000
CONFIG_USERLED=y
CONFIG_USERLED_LOWER=y

View file

@ -41,6 +41,9 @@
#if defined(CONFIG_BL808_SPI0) || defined(CONFIG_BL808_SPI1) #if defined(CONFIG_BL808_SPI0) || defined(CONFIG_BL808_SPI1)
#include "bl808_spi.h" #include "bl808_spi.h"
#endif #endif
#ifdef CONFIG_BL808_TIMERS
#include "bl808_timer.h"
#endif
#include "bl808_gpadc.h" #include "bl808_gpadc.h"
/**************************************************************************** /****************************************************************************
@ -168,9 +171,7 @@ void board_late_initialize(void)
/* Perform board-specific initialization */ /* Perform board-specific initialization */
#ifdef CONFIG_BL808_GPADC #ifdef CONFIG_BL808_GPADC
bl808_gpadc_init(); bl808_gpadc_init();
#endif #endif
#ifdef CONFIG_BL808_SPI0 #ifdef CONFIG_BL808_SPI0
@ -183,6 +184,10 @@ void board_late_initialize(void)
spi_register(spi1, 1); spi_register(spi1, 1);
#endif #endif
#ifdef CONFIG_BL808_TIMERS
bl808_timer_init();
#endif
#ifdef CONFIG_NSH_ARCHINIT #ifdef CONFIG_NSH_ARCHINIT
mount(NULL, "/proc", "procfs", 0, NULL); mount(NULL, "/proc", "procfs", 0, NULL);