mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 08:38:38 +08:00
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:
parent
42c9a829da
commit
049a6da098
11 changed files with 814 additions and 4 deletions
|
@ -150,3 +150,9 @@ spi
|
|||
This configuration enables support for SPI0 and spitool.
|
||||
By default, GPIO14 is MISO, 13 is MOSI, 15 is SCLK and 12 is SS.
|
||||
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.
|
||||
|
|
|
@ -52,7 +52,7 @@ I2C No
|
|||
I2S No
|
||||
PWM No
|
||||
SPI Yes
|
||||
Timers No
|
||||
Timers Yes
|
||||
UART Yes
|
||||
USB No
|
||||
=========== ======= ====================
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
#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_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)
|
||||
|
||||
/* 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_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_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 */
|
||||
|
|
|
@ -224,4 +224,9 @@ config BL808_SPI1_SS
|
|||
|
||||
endif
|
||||
|
||||
config BL808_TIMERS
|
||||
bool "Timers"
|
||||
default n
|
||||
select TIMER
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -28,4 +28,4 @@ HEAD_ASRC = bl808_head.S
|
|||
CHIP_CSRCS = bl808_start.c bl808_irq_dispatch.c bl808_irq.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_gpadc.c bl808_spi.c
|
||||
CHIP_CSRCS += bl808_gpadc.c bl808_spi.c bl808_timer.c
|
||||
|
|
549
arch/risc-v/src/bl808/bl808_timer.c
Normal file
549
arch/risc-v/src/bl808/bl808_timer.c
Normal 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 */
|
39
arch/risc-v/src/bl808/bl808_timer.h
Normal file
39
arch/risc-v/src/bl808/bl808_timer.h
Normal 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 */
|
|
@ -34,11 +34,13 @@
|
|||
#define BL808_UART0_BASE 0x2000a000ul
|
||||
#define BL808_UART1_BASE 0x2000a100ul
|
||||
#define BL808_SPI0_BASE 0x2000a200ul
|
||||
#define BL808_TIMER0_BASE 0x2000a500ul
|
||||
#define BL808_UART2_BASE 0x2000aa00ul
|
||||
#define BL808_AON_BASE 0x2000f000ul
|
||||
#define BL808_UART3_BASE 0x30002000ul
|
||||
#define BL808_MM_GLB_BASE 0x30007000ul
|
||||
#define BL808_SPI1_BASE 0x30008000ul
|
||||
#define BL808_TIMER1_BASE 0x30009000ul
|
||||
#define BL808_PLIC_BASE 0xe0000000ul
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H */
|
||||
|
|
100
arch/risc-v/src/bl808/hardware/bl808_timer.h
Normal file
100
arch/risc-v/src/bl808/hardware/bl808_timer.h
Normal 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 */
|
100
boards/risc-v/bl808/ox64/configs/timer/defconfig
Normal file
100
boards/risc-v/bl808/ox64/configs/timer/defconfig
Normal 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
|
|
@ -41,6 +41,9 @@
|
|||
#if defined(CONFIG_BL808_SPI0) || defined(CONFIG_BL808_SPI1)
|
||||
#include "bl808_spi.h"
|
||||
#endif
|
||||
#ifdef CONFIG_BL808_TIMERS
|
||||
#include "bl808_timer.h"
|
||||
#endif
|
||||
#include "bl808_gpadc.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -168,9 +171,7 @@ void board_late_initialize(void)
|
|||
/* Perform board-specific initialization */
|
||||
|
||||
#ifdef CONFIG_BL808_GPADC
|
||||
|
||||
bl808_gpadc_init();
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BL808_SPI0
|
||||
|
@ -183,6 +184,10 @@ void board_late_initialize(void)
|
|||
spi_register(spi1, 1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BL808_TIMERS
|
||||
bl808_timer_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_ARCHINIT
|
||||
|
||||
mount(NULL, "/proc", "procfs", 0, NULL);
|
||||
|
|
Loading…
Reference in a new issue