mirror of
https://github.com/apache/nuttx.git
synced 2026-05-13 18:48:11 +08:00
bl602: Add initial DMA support, including SPI over DMA.
This commit is contained in:
committed by
Alan Carvalho de Assis
parent
d247e8d1d2
commit
102c63be9e
@@ -7,6 +7,11 @@ comment "BL602 Configuration Options"
|
||||
|
||||
menu "BL602 Peripheral Support"
|
||||
|
||||
config BL602_DMA
|
||||
bool "DMA"
|
||||
default n
|
||||
select ARCH_DMA
|
||||
|
||||
config BL602_HAVE_UART0
|
||||
bool "UART0"
|
||||
select BL602_UART0
|
||||
@@ -42,9 +47,23 @@ config BL602_PWM0
|
||||
config BL602_I2C0
|
||||
bool "I2C0"
|
||||
|
||||
config BL602_I2C_DMA
|
||||
bool "I2C DMA support"
|
||||
default n
|
||||
depends on BL602_DMA
|
||||
---help---
|
||||
Select to enable DMA SPI transfers
|
||||
|
||||
config BL602_SPI0
|
||||
bool "SPI0"
|
||||
|
||||
config BL602_SPI_DMA
|
||||
bool "SPI DMA support"
|
||||
default n
|
||||
depends on BL602_DMA
|
||||
---help---
|
||||
Select to enable DMA SPI transfers
|
||||
|
||||
config BL602_RTC
|
||||
bool "RTC"
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ ifeq ($(CONFIG_RTC_DRIVER),y)
|
||||
CHIP_CSRCS += bl602_rtc.c bl602_rtc_lowerhalf.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BL602_DMA),y)
|
||||
CHIP_CSRCS += bl602_dma.c
|
||||
endif
|
||||
|
||||
CHIP_CSRCS += bl602_glb.c bl602_gpio.c bl602_hbn.c bl602_systemreset.c
|
||||
|
||||
ifeq ($(CONFIG_BL602_WIRELESS),y)
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/bl602/bl602_dma.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 <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "riscv_internal.h"
|
||||
#include "hardware/bl602_dma.h"
|
||||
#include "bl602_dma.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes one DMA channel */
|
||||
|
||||
struct dma_channel_s
|
||||
{
|
||||
uint8_t chan; /* DMA channel number (0-BL602_DMA_NCHANNELS) */
|
||||
bool inuse; /* TRUE: The DMA channel is in use */
|
||||
bl602_dma_callback_t callback; /* Callback invoked when the DMA completes */
|
||||
void *arg; /* Argument passed to callback function */
|
||||
};
|
||||
|
||||
/* This structure describes the state of the DMA controller */
|
||||
|
||||
struct dma_controller_s
|
||||
{
|
||||
sem_t exclsem; /* Protects channel table */
|
||||
sem_t chansem; /* Count of free channels */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the overall state of the DMA controller */
|
||||
|
||||
static struct dma_controller_s g_dmac;
|
||||
|
||||
/* This is the array of all DMA channels */
|
||||
|
||||
static struct dma_channel_s g_dmach[BL602_DMA_NCHANNELS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_int_handler
|
||||
*
|
||||
* Description:
|
||||
* DMA interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int bl602_dma_int_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
/* We need to ack the IRQ or a mess is made */
|
||||
|
||||
/* Itterate over each of the channels checking for and clearing:
|
||||
* DMA_INTTCSTATUS
|
||||
* DMA_INTERRORSTATUS
|
||||
*/
|
||||
|
||||
uint8_t ch;
|
||||
uint32_t tc_status;
|
||||
uint32_t err_status;
|
||||
|
||||
tc_status = getreg32(BL602_DMA_INTTCSTATUS) & DMA_INTTCSTATUS_MASK;
|
||||
err_status = getreg32(BL602_DMA_INTERRORSTATUS) & DMA_INTERRORSTATUS_MASK;
|
||||
|
||||
for (ch = 0; ch < BL602_DMA_NCHANNELS; ch++)
|
||||
{
|
||||
if (tc_status & (1 << ch))
|
||||
{
|
||||
dmainfo("CH %d TC Int fired\n", ch);
|
||||
putreg32((1 << ch), BL602_DMA_INTTCCLEAR);
|
||||
if (g_dmach[ch].callback != NULL)
|
||||
{
|
||||
g_dmach[ch].callback(
|
||||
ch,
|
||||
BL602_DMA_INT_EVT_TC,
|
||||
g_dmach[ch].arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (err_status & (1 << ch))
|
||||
{
|
||||
dmainfo("CH %d Error Int fired\n", ch);
|
||||
putreg32((1 << ch), BL602_DMA_INTERRCLR);
|
||||
g_dmach[ch].callback(ch, BL602_DMA_INT_EVT_ERR, g_dmach[ch].arg);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_request
|
||||
*
|
||||
* Description:
|
||||
* Allocate a new DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* 0-3: DMA channel
|
||||
* -1: Failed
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int8_t bl602_dma_channel_request(bl602_dma_callback_t callback, void *arg)
|
||||
{
|
||||
struct dma_channel_s *dmach;
|
||||
unsigned int ch;
|
||||
int ret;
|
||||
|
||||
/* Take a count from the channel counting semaphore. We may block
|
||||
* if there are no free channels. When we get the count, then we can
|
||||
* be assured that a channel is available in the channel list and is
|
||||
* reserved for us.
|
||||
*/
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&g_dmac.chansem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the DMA channel list */
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&g_dmac.exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
nxsem_post(&g_dmac.chansem);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Search for an available DMA channel */
|
||||
|
||||
for (ch = 0, dmach = NULL; ch < BL602_DMA_NCHANNELS; ch++)
|
||||
{
|
||||
struct dma_channel_s *candidate = &g_dmach[ch];
|
||||
if (!candidate->inuse)
|
||||
{
|
||||
dmainfo("DMA Channel %u assigned.\n", ch);
|
||||
dmach = candidate;
|
||||
dmach->inuse = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&g_dmac.exclsem);
|
||||
|
||||
/* Since we have reserved a DMA descriptor by taking a count from chansem,
|
||||
* it would be a serious logic failure if we could not find a free channel
|
||||
* for our use.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(dmach);
|
||||
dmach->callback = callback;
|
||||
dmach->arg = arg;
|
||||
return dmach->chan;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_release
|
||||
*
|
||||
* Description:
|
||||
* Release a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_release(uint8_t channel_id)
|
||||
{
|
||||
/* Get exclusive access to the DMA channel list */
|
||||
|
||||
if (nxsem_wait_uninterruptible(&g_dmac.exclsem) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Verify if the channel is actually in use */
|
||||
|
||||
if (g_dmach[channel_id].inuse)
|
||||
{
|
||||
/* This channel was infact in use, release it and increment the
|
||||
* count of free channels for use.
|
||||
*/
|
||||
|
||||
g_dmach[channel_id].inuse = false;
|
||||
nxsem_post(&g_dmac.chansem);
|
||||
}
|
||||
|
||||
nxsem_post(&g_dmac.exclsem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_start
|
||||
*
|
||||
* Description:
|
||||
* Start a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_start(uint8_t channel_id)
|
||||
{
|
||||
/* Unmask interrupts for:
|
||||
* - DMA_INT_TCOMPLETED
|
||||
* - DMA_INT_ERR
|
||||
* Enable Terminal Count interrupt.
|
||||
*/
|
||||
|
||||
modifyreg32(BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, channel_id),
|
||||
DMA_C0CONFIG_ITC | DMA_C0CONFIG_IE,
|
||||
0);
|
||||
modifyreg32(BL602_DMA_CH_N_REG(BL602_DMA_CONTROL_OFFSET, channel_id),
|
||||
0,
|
||||
DMA_C0CONTROL_I);
|
||||
|
||||
/* Enable channel */
|
||||
|
||||
modifyreg32(BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, channel_id),
|
||||
0,
|
||||
DMA_C0CONFIG_E);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_stop(uint8_t channel_id)
|
||||
{
|
||||
/* Disable channel */
|
||||
|
||||
modifyreg32(BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, channel_id),
|
||||
DMA_C0CONFIG_E,
|
||||
0);
|
||||
|
||||
/* Mask interrupts for:
|
||||
* - DMA_INT_TCOMPLETED
|
||||
* - DMA_INT_ERR
|
||||
*/
|
||||
|
||||
modifyreg32(BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, channel_id),
|
||||
0,
|
||||
DMA_C0CONFIG_ITC | DMA_C0CONFIG_IE);
|
||||
|
||||
/* Clear interrupts for channel in:
|
||||
* - DMA_INTTCCLEAR
|
||||
* - DMA_INTERRORSTATUS
|
||||
*/
|
||||
|
||||
putreg32((1 << channel_id), BL602_DMA_INTTCCLEAR);
|
||||
putreg32((1 << channel_id), BL602_DMA_INTERRCLR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_dma_initialize
|
||||
*
|
||||
* Description:
|
||||
* Intialize DMA controller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void weak_function riscv_dma_initialize(void)
|
||||
{
|
||||
uint8_t ch;
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
struct bl602_dmaregs_s regs;
|
||||
#endif
|
||||
|
||||
dmainfo("Initialize DMA\n");
|
||||
|
||||
/* Note we may want to set EN bits in DMAEN as part of clk_cfg2.
|
||||
* At reset these bits are already set to enabled, and the documentation
|
||||
* is a little thin around this. If we implement more low power
|
||||
* configuration we will want to be more clear about these bits.
|
||||
*/
|
||||
|
||||
/* Initialize the channel list */
|
||||
|
||||
nxsem_init(&g_dmac.exclsem, 0, 1);
|
||||
nxsem_init(&g_dmac.chansem, 0, BL602_DMA_NCHANNELS);
|
||||
|
||||
for (ch = 0; ch < BL602_DMA_NCHANNELS; ch++)
|
||||
{
|
||||
g_dmach[ch].chan = ch;
|
||||
|
||||
/* Disable the DMA channel */
|
||||
|
||||
putreg32(0, BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, ch));
|
||||
}
|
||||
|
||||
/* Attach DMA tranfer complete interrupt handler */
|
||||
|
||||
irq_attach(BL602_IRQ_DMA_ALL, bl602_dma_int_handler, NULL);
|
||||
up_enable_irq(BL602_IRQ_DMA_ALL);
|
||||
|
||||
/* Enable SMDMA controller */
|
||||
|
||||
modifyreg32(BL602_DMA_TOP_CONFIG, 0, DMA_TOP_CONFIG_E);
|
||||
|
||||
/* Dump DMA register state */
|
||||
|
||||
bl602_dmasample(®s);
|
||||
bl602_dmadump(®s, "Initialized DMA");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dmasample
|
||||
*
|
||||
* Description:
|
||||
* Sample DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
void bl602_dmasample(struct bl602_dmaregs_s *regs)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Sample DMA registers. */
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
regs->intstatus = getreg32(BL602_DMA_INTSTATUS);
|
||||
regs->inttcstatus = getreg32(BL602_DMA_INTTCSTATUS);
|
||||
regs->inttcclear = getreg32(BL602_DMA_INTTCCLEAR);
|
||||
regs->interrorstatus = getreg32(BL602_DMA_INTERRORSTATUS);
|
||||
regs->interrclr = getreg32(BL602_DMA_INTERRCLR);
|
||||
regs->rawinttcstatus = getreg32(BL602_DMA_RAWINTTCSTATUS);
|
||||
regs->rawinterrorstatus = getreg32(BL602_DMA_RAWINTERRORSTATUS);
|
||||
regs->enbldchns = getreg32(BL602_DMA_ENBLDCHNS);
|
||||
regs->softbreq = getreg32(BL602_DMA_SOFTBREQ);
|
||||
regs->softsreq = getreg32(BL602_DMA_SOFTSREQ);
|
||||
regs->softlbreq = getreg32(BL602_DMA_SOFTLBREQ);
|
||||
regs->softlsreq = getreg32(BL602_DMA_SOFTLSREQ);
|
||||
regs->top_config = getreg32(BL602_DMA_TOP_CONFIG);
|
||||
regs->sync = getreg32(BL602_DMA_SYNC);
|
||||
regs->c0srcaddr = getreg32(BL602_DMA_C0SRCADDR);
|
||||
regs->c0dstaddr = getreg32(BL602_DMA_C0DSTADDR);
|
||||
regs->c0lli = getreg32(BL602_DMA_C0LLI);
|
||||
regs->c0control = getreg32(BL602_DMA_C0CONTROL);
|
||||
regs->c0config = getreg32(BL602_DMA_C0CONFIG);
|
||||
regs->c1srcaddr = getreg32(BL602_DMA_C1SRCADDR);
|
||||
regs->c1dstaddr = getreg32(BL602_DMA_C1DSTADDR);
|
||||
regs->c1lli = getreg32(BL602_DMA_C1LLI);
|
||||
regs->c1control = getreg32(BL602_DMA_C1CONTROL);
|
||||
regs->c1config = getreg32(BL602_DMA_C1CONFIG);
|
||||
regs->c2srcaddr = getreg32(BL602_DMA_C2SRCADDR);
|
||||
regs->c2dstaddr = getreg32(BL602_DMA_C2DSTADDR);
|
||||
regs->c2lli = getreg32(BL602_DMA_C2LLI);
|
||||
regs->c2control = getreg32(BL602_DMA_C2CONTROL);
|
||||
regs->c2config = getreg32(BL602_DMA_C2CONFIG);
|
||||
regs->c3srcaddr = getreg32(BL602_DMA_C3SRCADDR);
|
||||
regs->c3dstaddr = getreg32(BL602_DMA_C3DSTADDR);
|
||||
regs->c3lli = getreg32(BL602_DMA_C3LLI);
|
||||
regs->c3control = getreg32(BL602_DMA_C3CONTROL);
|
||||
regs->c3config = getreg32(BL602_DMA_C3CONFIG);
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dmadump
|
||||
*
|
||||
* Description:
|
||||
* Dump previously sampled DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
void bl602_dmadump(const struct bl602_dmaregs_s *regs,
|
||||
const char *msg)
|
||||
{
|
||||
dmainfo("%s\n", msg);
|
||||
dmainfo(" DMA Registers:\n");
|
||||
dmainfo(" INTSTATUS: %08x\n", regs->intstatus);
|
||||
dmainfo(" INTTCSTATU: %08x\n", regs->inttcstatus);
|
||||
dmainfo(" INTTCCLEAR: %08x\n", regs->inttcclear);
|
||||
dmainfo(" INTERRORST: %08x\n", regs->interrorstatus);
|
||||
dmainfo(" INTERRCLR: %08x\n", regs->interrclr);
|
||||
dmainfo(" RAWINTTCST: %08x\n", regs->rawinttcstatus);
|
||||
dmainfo(" RAWINTERRO: %08x\n", regs->rawinterrorstatus);
|
||||
dmainfo(" ENBLDCHNS: %08x\n", regs->enbldchns);
|
||||
dmainfo(" SOFTBREQ: %08x\n", regs->softbreq);
|
||||
dmainfo(" SOFTSREQ: %08x\n", regs->softsreq);
|
||||
dmainfo(" SOFTLBREQ: %08x\n", regs->softlbreq);
|
||||
dmainfo(" SOFTLSREQ: %08x\n", regs->softlsreq);
|
||||
dmainfo(" TOP_CONFIG: %08x\n", regs->top_config);
|
||||
dmainfo(" SYNC: %08x\n", regs->sync);
|
||||
dmainfo(" === Channel 0 ===\n");
|
||||
dmainfo(" C0SRCADDR: %08x\n", regs->c0srcaddr);
|
||||
dmainfo(" C0DSTADDR: %08x\n", regs->c0dstaddr);
|
||||
dmainfo(" C0LLI: %08x\n", regs->c0lli);
|
||||
dmainfo(" C0CONTROL: %08x\n", regs->c0control);
|
||||
dmainfo(" C0CONFIG: %08x\n", regs->c0config);
|
||||
dmainfo(" === Channel 1 ===\n");
|
||||
dmainfo(" C1SRCADDR: %08x\n", regs->c1srcaddr);
|
||||
dmainfo(" C1DSTADDR: %08x\n", regs->c1dstaddr);
|
||||
dmainfo(" C1LLI: %08x\n", regs->c1lli);
|
||||
dmainfo(" C1CONTROL: %08x\n", regs->c1control);
|
||||
dmainfo(" C1CONFIG: %08x\n", regs->c1config);
|
||||
dmainfo(" === Channel 2 ===\n");
|
||||
dmainfo(" C2SRCADDR: %08x\n", regs->c2srcaddr);
|
||||
dmainfo(" C2DSTADDR: %08x\n", regs->c2dstaddr);
|
||||
dmainfo(" C2LLI: %08x\n", regs->c2lli);
|
||||
dmainfo(" C2CONTROL: %08x\n", regs->c2control);
|
||||
dmainfo(" C2CONFIG: %08x\n", regs->c2config);
|
||||
dmainfo(" === Channel 3 ===\n");
|
||||
dmainfo(" C3SRCADDR: %08x\n", regs->c3srcaddr);
|
||||
dmainfo(" C3DSTADDR: %08x\n", regs->c3dstaddr);
|
||||
dmainfo(" C3LLI: %08x\n", regs->c3lli);
|
||||
dmainfo(" C3CONTROL: %08x\n", regs->c3control);
|
||||
dmainfo(" C3CONFIG: %08x\n", regs->c3config);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,262 @@
|
||||
/****************************************************************************
|
||||
* arch/risc-v/src/bl602/bl602_dma.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_BL602_BL602_DMA_H
|
||||
#define __ARCH_RISCV_SRC_BL602_BL602_DMA_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define BL602_DMA_NCHANNELS 4
|
||||
#define BL602_DMA_INT_EVT_TC 0 /* Interrupt callback status Transfer Complete */
|
||||
#define BL602_DMA_INT_EVT_ERR 1 /* Interrupt callback status Error */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
struct bl602_dmaregs_s
|
||||
{
|
||||
uint32_t intstatus; /* Interrupt status. */
|
||||
uint32_t inttcstatus; /* Interrupt terminal count request status. */
|
||||
uint32_t inttcclear; /* Terminal count request clear. */
|
||||
uint32_t interrorstatus; /* Interrupt error status. */
|
||||
uint32_t interrclr; /* Interrupt error clear. */
|
||||
uint32_t rawinttcstatus; /* Status of the terminal count interrupt prior to masking. */
|
||||
uint32_t rawinterrorstatus; /* Status of the error interrupt prior to masking. */
|
||||
uint32_t enbldchns; /* Channel enable status. */
|
||||
uint32_t softbreq; /* Software burst request. */
|
||||
uint32_t softsreq; /* Software single request. */
|
||||
uint32_t softlbreq; /* Software last burst request. */
|
||||
uint32_t softlsreq; /* Software last single request. */
|
||||
uint32_t top_config; /* DMA general configuration. */
|
||||
uint32_t sync; /* DMA request asynchronous setting. */
|
||||
uint32_t c0srcaddr; /* Channel DMA source address. */
|
||||
uint32_t c0dstaddr; /* Channel DMA Destination address. */
|
||||
uint32_t c0lli; /* Channel DMA link list. */
|
||||
uint32_t c0control; /* Channel DMA bus control. */
|
||||
uint32_t c0config; /* Channel DMA configuration. */
|
||||
uint32_t c1srcaddr; /* Channel DMA source address. */
|
||||
uint32_t c1dstaddr; /* Channel DMA Destination address. */
|
||||
uint32_t c1lli; /* Channel DMA link list. */
|
||||
uint32_t c1control; /* Channel DMA bus control. */
|
||||
uint32_t c1config; /* Channel DMA configuration. */
|
||||
uint32_t c2srcaddr; /* Channel DMA source address. */
|
||||
uint32_t c2dstaddr; /* Channel DMA Destination address. */
|
||||
uint32_t c2lli; /* Channel DMA link list. */
|
||||
uint32_t c2control; /* Channel DMA bus control. */
|
||||
uint32_t c2config; /* Channel DMA configuration. */
|
||||
uint32_t c3srcaddr; /* Channel DMA source address. */
|
||||
uint32_t c3dstaddr; /* Channel DMA Destination address. */
|
||||
uint32_t c3lli; /* Channel DMA link list. */
|
||||
uint32_t c3control; /* Channel DMA bus control. */
|
||||
uint32_t c3config; /* Channel DMA configuration. */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Configuration for the LLI Control entry, defined as matching
|
||||
* the DMA channel control register.
|
||||
*/
|
||||
|
||||
begin_packed_struct struct bl602_dma_ctrl_s
|
||||
{
|
||||
uint32_t transfer_size : 12;
|
||||
uint32_t src_burst_size : 3;
|
||||
uint32_t dst_burst_size : 3;
|
||||
uint32_t src_width : 3;
|
||||
uint32_t dst_width : 3;
|
||||
uint32_t sld : 1;
|
||||
uint32_t rsvd : 1;
|
||||
uint32_t src_increment : 1;
|
||||
uint32_t dst_increment : 1;
|
||||
uint32_t protect : 3;
|
||||
uint32_t tc_int_en : 1;
|
||||
} end_packed_struct;
|
||||
|
||||
/* Configuration for the LLI packed data.
|
||||
* This must be aligned to uint32 pointer.
|
||||
*/
|
||||
|
||||
begin_packed_struct struct aligned_data(4) bl602_lli_ctrl_s
|
||||
{
|
||||
uint32_t src_addr;
|
||||
uint32_t dst_addr;
|
||||
uint32_t next_lli; /* Address for next LLI entry */
|
||||
struct bl602_dma_ctrl_s dma_ctrl; /* Control register config for entry */
|
||||
} end_packed_struct;
|
||||
|
||||
/* Description:
|
||||
* This is the type of the callback that is used to inform the user of the
|
||||
* completion of the DMA.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel - Refers to the DMA channel
|
||||
* status - A bit encoded value that provides the completion status.
|
||||
* See the BL602_DMA_INT_EVT_* definitions above.
|
||||
* arg - A user-provided value.
|
||||
*/
|
||||
|
||||
typedef void (*bl602_dma_callback_t) \
|
||||
(uint8_t channel, uint8_t status, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_request
|
||||
*
|
||||
* Description:
|
||||
* Allocate a new DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* 0-3: DMA channel
|
||||
* -1: Failed
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int8_t bl602_dma_channel_request(bl602_dma_callback_t callback, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_release
|
||||
*
|
||||
* Description:
|
||||
* Release a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_release(uint8_t channel);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_start
|
||||
*
|
||||
* Description:
|
||||
* Start a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_start(uint8_t channel_id);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_channel_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop a DMA channel.
|
||||
*
|
||||
* Input Parameters:
|
||||
* channel: DMA channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_channel_stop(uint8_t channel_id);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dma_init
|
||||
*
|
||||
* Description:
|
||||
* Intialize DMA controller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int bl602_dma_init(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dmasample
|
||||
*
|
||||
* Description:
|
||||
* Sample DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
void bl602_dmasample(struct bl602_dmaregs_s *regs);
|
||||
#else
|
||||
# define bl602_dmasample(regs)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bl602_dmadump
|
||||
*
|
||||
* Description:
|
||||
* Dump previously sampled DMA register contents
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
void bl602_dmadump(const struct bl602_dmaregs_s *regs, const char *msg);
|
||||
#else
|
||||
# define bl602_dmadump(regs,msg)
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_RISCV_SRC_BL602_BL602_DMA_H */
|
||||
@@ -31,6 +31,7 @@
|
||||
#define BL602_ROMAPI_FUNC(idx) (*(uintptr_t *)(BL602_ROMAPI_BASE + (idx)*4))
|
||||
|
||||
#define BL602_ROMAPI_ASM_DELAY_US BL602_ROMAPI_FUNC(20)
|
||||
#define BL602_ROMAPI_MEMCPY4 BL602_ROMAPI_FUNC(24)
|
||||
#define BL602_ROMAPI_EFUSE_CTRL_LOAD_R0 BL602_ROMAPI_FUNC(31)
|
||||
#define BL602_ROMAPI_RST_SYSTEM BL602_ROMAPI_FUNC(47)
|
||||
#define BL602_ROMAPI_RST_CPU_SW BL602_ROMAPI_FUNC(48)
|
||||
@@ -43,4 +44,6 @@
|
||||
#define BL602_ROMAPI_SFLASH_WRITE_WITHLOCK BL602_ROMAPI_FUNC(171)
|
||||
#define BL602_ROMAPI_SFLASH_EREASE_WITHLOCK BL602_ROMAPI_FUNC(172)
|
||||
|
||||
#define bl602_romapi_memcpy_4 ((uint32_t* (*) (uint32_t*, const uint32_t*, uint32_t))BL602_ROMAPI_MEMCPY4)
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_BL602_BL602_ROMAPI_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,8 +42,6 @@ extern "C"
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BL602_SPI0
|
||||
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <nuttx/spi/spi_transfer.h>
|
||||
|
||||
@@ -77,8 +75,6 @@ struct spi_dev_s *bl602_spibus_initialize(int port);
|
||||
|
||||
int bl602_spibus_uninitialize(struct spi_dev_s *dev);
|
||||
|
||||
#endif /* CONFIG_BL602_SPI0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -106,6 +106,18 @@
|
||||
#define BL602_DMA_C3CONTROL (BL602_DMA_BASE + BL602_DMA_C3CONTROL_OFFSET)
|
||||
#define BL602_DMA_C3CONFIG (BL602_DMA_BASE + BL602_DMA_C3CONFIG_OFFSET)
|
||||
|
||||
/* Channel register helpers *************************************************/
|
||||
|
||||
#define BL602_DMA_CH_REG_OFFSET 0x000100 /* Offset between channels */
|
||||
#define BL602_DMA_CH_REG_BASE BL602_DMA_C0SRCADDR
|
||||
#define BL602_DMA_SRCADDR_OFFSET 0x000000 /* CnSrcAddr */
|
||||
#define BL602_DMA_DSTADDR_OFFSET 0x000004 /* CnDstAddr */
|
||||
#define BL602_DMA_LLI_OFFSET 0x000008 /* CnLLI */
|
||||
#define BL602_DMA_CONTROL_OFFSET 0x00000c /* CnControl */
|
||||
#define BL602_DMA_CONFIG_OFFSET 0x000010 /* CnConfig */
|
||||
|
||||
#define BL602_DMA_CH_N_REG(reg, ch) ((BL602_DMA_CH_REG_BASE + (BL602_DMA_CH_REG_OFFSET * ch)) + reg)
|
||||
|
||||
/* Register bit definitions *************************************************/
|
||||
|
||||
#define DMA_INTSTATUS_MASK (0xff)
|
||||
@@ -251,4 +263,23 @@
|
||||
#define DMA_C3CONFIG_SRCPERIPHERAL_MASK (0x1f << DMA_C3CONFIG_SRCPERIPHERAL_SHIFT)
|
||||
#define DMA_C3CONFIG_E (1 << 0)
|
||||
|
||||
#define BL602_DMA_TRNS_M2M (0) /* DMA memory to memory */
|
||||
#define BL602_DMA_TRNS_M2P (1) /* DMA memory to peripheral */
|
||||
#define BL602_DMA_TRNS_P2M (2) /* DMA peripheral to memory */
|
||||
#define BL602_DMA_TRNS_P2P (3) /* DMA peripheral to peripheral */
|
||||
|
||||
#define BL602_DMA_REQ_UART0_RX (0) /* DMA request peripheral UART0 RX */
|
||||
#define BL602_DMA_REQ_UART0_TX (1) /* DMA request peripheral UART0 TX */
|
||||
#define BL602_DMA_REQ_UART1_RX (2) /* DMA request peripheral UART1 RX */
|
||||
#define BL602_DMA_REQ_UART1_TX (3) /* DMA request peripheral UART1 TX */
|
||||
#define BL602_DMA_REQ_I2C_RX (6) /* DMA request peripheral I2C RX */
|
||||
#define BL602_DMA_REQ_I2C_TX (7) /* DMA request peripheral I2C TX */
|
||||
#define BL602_DMA_REQ_SPI_RX (10) /* DMA request peripheral SPI RX */
|
||||
#define BL602_DMA_REQ_SPI_TX (11) /* DMA request peripheral SPI TX */
|
||||
#define BL602_DMA_REQ_I2S_RX (20) /* DMA request peripheral SPI RX */
|
||||
#define BL602_DMA_REQ_I2S_TX (21) /* DMA request peripheral SPI TX */
|
||||
#define BL602_DMA_REQ_GPADC0 (22) /* DMA request peripheral GPADC0 */
|
||||
#define BL602_DMA_REQ_GPADC1 (23) /* DMA request peripheral GPADC1 */
|
||||
#define BL602_DMA_REQ_NONE (0 ) /* DMA request peripheral None */
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_BL602_HARDWARE_BL602_DMA_H */
|
||||
|
||||
@@ -105,6 +105,19 @@ void up_initialize(void)
|
||||
riscv_pminitialize();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA
|
||||
/* Initialize the DMA subsystem if the weak function arm_dma_initialize has
|
||||
* been brought into the build
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
|
||||
if (riscv_dma_initialize)
|
||||
#endif
|
||||
{
|
||||
riscv_dma_initialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the serial device driver */
|
||||
|
||||
#ifdef USE_SERIALDRIVER
|
||||
|
||||
@@ -232,6 +232,12 @@ void riscv_pminitialize(void);
|
||||
# define riscv_pminitialize()
|
||||
#endif
|
||||
|
||||
/* DMA **********************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA
|
||||
void weak_function riscv_dma_initialize(void);
|
||||
#endif
|
||||
|
||||
/* Low level serial output **************************************************/
|
||||
|
||||
void riscv_lowputc(char ch);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# 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_LIBC_FLOATINGPOINT is not set
|
||||
# CONFIG_LIBC_LONG_LONG is not set
|
||||
# CONFIG_NDEBUG is not set
|
||||
# CONFIG_NSH_ARGCAT is not set
|
||||
# CONFIG_NSH_CMDPARMS is not set
|
||||
# CONFIG_NSH_DISABLE_LOSMART is not set
|
||||
CONFIG_ARCH="risc-v"
|
||||
CONFIG_ARCH_BOARD="bl602evb"
|
||||
CONFIG_ARCH_BOARD_BL602EVB=y
|
||||
CONFIG_ARCH_CHIP="bl602"
|
||||
CONFIG_ARCH_CHIP_BL602=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=8192
|
||||
CONFIG_ARCH_RISCV=y
|
||||
CONFIG_ARCH_STACKDUMP=y
|
||||
CONFIG_BINFMT_DISABLE=y
|
||||
CONFIG_BL602_DMA=y
|
||||
CONFIG_BL602_HAVE_UART0=y
|
||||
CONFIG_BL602_I2C0=y
|
||||
CONFIG_BL602_I2C_DMA=y
|
||||
CONFIG_BL602_SPI0=y
|
||||
CONFIG_BL602_SPI_DMA=y
|
||||
CONFIG_BL602_TIMER0=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=10000
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_SYMBOLS=y
|
||||
CONFIG_DEV_ZERO=y
|
||||
CONFIG_DISABLE_ENVIRON=y
|
||||
CONFIG_DISABLE_MQUEUE=y
|
||||
CONFIG_DISABLE_POSIX_TIMERS=y
|
||||
CONFIG_DISABLE_PSEUDOFS_OPERATIONS=y
|
||||
CONFIG_EXAMPLES_HELLO=y
|
||||
CONFIG_EXAMPLES_HELLO_STACKSIZE=8192
|
||||
CONFIG_EXAMPLES_TIMER=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=8192
|
||||
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||
CONFIG_INIT_STACKSIZE=8192
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_LIBC_PERROR_STDOUT=y
|
||||
CONFIG_LIBC_STRERROR=y
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||
CONFIG_NSH_ARCHINIT=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=64
|
||||
CONFIG_NSH_LINELEN=64
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_NSH_STRERROR=y
|
||||
CONFIG_PTHREAD_MUTEX_UNSAFE=y
|
||||
CONFIG_PTHREAD_STACK_DEFAULT=8192
|
||||
CONFIG_RAM_SIZE=134217728
|
||||
CONFIG_RAM_START=0xc0800000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SIG_PREALLOC_IRQ_ACTIONS=4
|
||||
CONFIG_SPI=y
|
||||
CONFIG_STACK_COLORATION=y
|
||||
CONFIG_START_DAY=20
|
||||
CONFIG_START_MONTH=3
|
||||
CONFIG_START_YEAR=2020
|
||||
CONFIG_STDIO_DISABLE_BUFFERING=y
|
||||
CONFIG_SYSTEM_I2CTOOL=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_SYSTEM_SPITOOL=y
|
||||
CONFIG_TASK_NAME_SIZE=12
|
||||
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=8192
|
||||
CONFIG_TESTING_GETPRIME=y
|
||||
CONFIG_TIMER=y
|
||||
CONFIG_TIMER_ARCH=y
|
||||
CONFIG_UART0_BAUD=2000000
|
||||
CONFIG_UART0_RXBUFSIZE=128
|
||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_UART0_TXBUFSIZE=128
|
||||
Reference in New Issue
Block a user