bl602: Add initial DMA support, including SPI over DMA.

This commit is contained in:
Brennan Ashton 2022-08-14 16:29:30 -07:00 committed by Alan Carvalho de Assis
parent d247e8d1d2
commit 102c63be9e
11 changed files with 1327 additions and 14 deletions

View File

@ -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"

View File

@ -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)

View File

@ -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(&regs);
bl602_dmadump(&regs, "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

View File

@ -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 */

View File

@ -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 */

View File

@ -33,15 +33,22 @@
#include <sys/types.h>
#include <nuttx/arch.h>
#include <nuttx/compiler.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/semaphore.h>
#include <nuttx/signal.h>
#include <nuttx/spi/spi.h>
#include <arch/board/board.h>
#include "bl602_glb.h"
#include "bl602_gpio.h"
#include "bl602_romapi.h"
#include "bl602_spi.h"
#include "bl602_dma.h"
#include "hardware/bl602_dma.h"
#include "hardware/bl602_glb.h"
#include "hardware/bl602_spi.h"
#include "hardware/bl602_hbn.h"
@ -52,6 +59,7 @@
****************************************************************************/
#define SPI_FREQ_DEFAULT 400000
#define LLI_BUFF_SIZE 2048 /* Maximum transaction count per LLI entry. */
/****************************************************************************
* Private Types
@ -126,7 +134,8 @@ struct bl602_spi_priv_s
/* Interrupt wait semaphore */
sem_t sem_isr;
sem_t sem_isr_tx;
sem_t sem_isr_rx;
uint32_t frequency; /* Requested clock frequency */
uint32_t actual; /* Actual clock frequency */
@ -136,7 +145,8 @@ struct bl602_spi_priv_s
/* Actual SPI send/receive bits once transmission */
uint8_t nbits;
uint8_t dma_chan;
int8_t dma_txchan;
int8_t dma_rxchan;
};
/****************************************************************************
@ -227,7 +237,9 @@ static struct bl602_spi_priv_s bl602_spi_priv =
{
.ops = &bl602_spi_ops
},
.config = &bl602_spi_config
.config = &bl602_spi_config,
.dma_rxchan = -1,
.dma_txchan = -1,
};
#endif /* CONFIG_BL602_SPI0 */
@ -236,6 +248,38 @@ static struct bl602_spi_priv_s bl602_spi_priv =
* Private Functions
****************************************************************************/
#ifdef CONFIG_BL602_SPI_DMA
static void bl602_dma_rx_callback(uint8_t channel, uint8_t status, void *arg)
{
struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)arg;
UNUSED(channel);
spiinfo("RX interrupt fired with status %u\n", status);
if (status == BL602_DMA_INT_EVT_TC)
{
nxsem_post(&priv->sem_isr_rx);
}
else
{
spierr("DMA transfer failed for RX.\n");
}
}
static void bl602_dma_tx_callback(uint8_t channel, uint8_t status, void *arg)
{
struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)arg;
UNUSED(channel);
spiinfo("TX interrupt fired with status %u\n", status);
if (status == BL602_DMA_INT_EVT_TC)
{
nxsem_post(&priv->sem_isr_tx);
}
else
{
spierr("DMA transfer failed for TX.\n");
}
}
#endif
/****************************************************************************
* Name: bl602_check_with_new_prescale
*
@ -773,6 +817,168 @@ static int bl602_spi_hwfeatures(struct spi_dev_s *dev,
}
#endif
/****************************************************************************
* Name: lli_list_init
*
* Description:
* Configure the LLI structure for DMA transactions with SPI
*
* Input Parameters:
* priv - Device-specific state data
* tx_lli - A pointer to the LLI structures for TX.
* rx_lli - A pointer to the LLI structures for RX.
* tx_buffer - A pointer to the transaction buffer for TX.
* rx_buffer - A pointer to the transaction buffer for RX.
* Buffer is null if TX only.
* nwords - the length of data to send from the buffer in number of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
*
* Returned Value:
* Error state - 0 on success.
*
****************************************************************************/
#ifdef CONFIG_BL602_SPI_DMA
static int lli_list_init(struct bl602_spi_priv_s *priv,
struct bl602_lli_ctrl_s **tx_lli,
struct bl602_lli_ctrl_s **rx_lli,
const void *txbuffer,
void *rxbuffer, size_t nwords)
{
uint8_t i;
uint32_t count;
uint32_t remainder;
struct bl602_dma_ctrl_s dma_ctrl;
/* Determine the how many LLI entries will be required */
count = (nwords * priv->nbits / 8) / LLI_BUFF_SIZE;
remainder = (nwords * priv->nbits / 8) % LLI_BUFF_SIZE;
/* If LLI entry cannot be fully packed with data, add an additional entry
* for the remainder entry.
*/
if (remainder != 0)
{
count = count + 1;
}
/* Set the base config that will be used for each entry */
dma_ctrl.src_width = (priv->nbits / 8) - 1; /* 8/16/32 bits */
dma_ctrl.dst_width = dma_ctrl.src_width;
dma_ctrl.src_burst_size = 0; /* 1 item per transaction */
dma_ctrl.dst_burst_size = 0; /* 1 item per transaction */
dma_ctrl.protect = 0;
dma_ctrl.tc_int_en = 0; /* We will overwrite this in the last entry */
dma_ctrl.rsvd = 0;
dma_ctrl.sld = 0; /* Not used for non mem-to-mem transfers. */
/* We will set these per entry:
* - transfer_size
* - src_increment
* - dst_increment
*/
/* Allocate the transfer block.
* TODO consider supporting pre-allocation of these structures.
* most transaction will only use a single LLI, so we could
* actually place the single LLI structure on the stack (4*4 bytes)
*/
*tx_lli = kmm_malloc(sizeof(struct bl602_lli_ctrl_s) * count);
if (*tx_lli == NULL)
{
spierr("Failed to allocate lli for tx.\n");
return -1;
}
if (rxbuffer != NULL)
{
*rx_lli = kmm_malloc(sizeof(struct bl602_lli_ctrl_s) * count);
if (*rx_lli == NULL)
{
spierr("Failed to allocate lli for rx.\n");
kmm_free(*tx_lli);
return -1;
}
}
else
{
*rx_lli = NULL;
}
for (i = 0; i < count; i++)
{
/* Check if this is the final entry and there is remainder set */
if ((i == (count - 1)) && (remainder != 0))
{
dma_ctrl.transfer_size = remainder;
}
else
{
dma_ctrl.transfer_size = LLI_BUFF_SIZE;
}
/* Configure tx side */
{
dma_ctrl.dst_increment = 0;
dma_ctrl.src_increment = 1;
(*tx_lli)[i].dma_ctrl = dma_ctrl;
(*tx_lli)[i].dst_addr = BL602_SPI_FIFO_WDATA;
(*tx_lli)[i].src_addr = \
(uint32_t)txbuffer + (dma_ctrl.src_width * i * LLI_BUFF_SIZE);
/* Assume last entry, we will overwrite as needed. */
(*tx_lli)[i].next_lli = 0;
/* Link entry */
if (i != 0)
{
(*tx_lli)[i - 1].next_lli = (uint32_t)&(*tx_lli)[i];
}
}
/* Configure rx side */
if (rxbuffer != NULL)
{
dma_ctrl.dst_increment = 1;
dma_ctrl.src_increment = 0;
(*rx_lli)[i].dma_ctrl = dma_ctrl;
(*rx_lli)[i].dst_addr = \
(uint32_t)rxbuffer + (dma_ctrl.dst_width * i * LLI_BUFF_SIZE);
(*rx_lli)[i].src_addr = BL602_SPI_FIFO_RDATA;
(*rx_lli)[i].next_lli = 0; /* Assume last entry, we will overwrite as needed. */
/* Link entry */
if (i != 0)
{
(*rx_lli)[i - 1].next_lli = (uint32_t)&(*rx_lli)[i];
}
}
}
(*tx_lli)[count - 1].dma_ctrl.tc_int_en = 1;
if (rxbuffer != NULL)
{
(*rx_lli)[count - 1].dma_ctrl.tc_int_en = 1;
}
return 0;
}
#endif
/****************************************************************************
* Name: bl602_spi_dma_exchange
*
@ -794,13 +1000,97 @@ static int bl602_spi_hwfeatures(struct spi_dev_s *dev,
*
****************************************************************************/
#ifdef CONFIG_BL602_SPI_DMA
static void bl602_spi_dma_exchange(struct bl602_spi_priv_s *priv,
const void *txbuffer,
void *rxbuffer, uint32_t nwords)
{
spierr("SPI dma not supported\n");
DEBUGPANIC();
int err;
#ifdef CONFIG_DEBUG_DMA_INFO
struct bl602_dmaregs_s regs;
#endif
struct bl602_lli_ctrl_s *tx_lli;
struct bl602_lli_ctrl_s *rx_lli;
/* Enable master */
modifyreg32(BL602_SPI_CFG, SPI_CFG_CR_S_EN, SPI_CFG_CR_M_EN);
err = lli_list_init(priv, &tx_lli, &rx_lli, txbuffer, rxbuffer, nwords);
if (err < 0)
{
spierr("Failed to initalize DMA LLI\n");
return;
}
/* Configure DMA controller with LLI.
* This needs to be set using the ROM API from TCM to initialize all 4
* registers from the LLI structure.
*/
bl602_romapi_memcpy_4(
(uint32_t *)BL602_DMA_CH_N_REG(BL602_DMA_SRCADDR_OFFSET,
priv->dma_txchan),
(uint32_t *)tx_lli, 4);
if (rxbuffer != NULL)
{
bl602_romapi_memcpy_4(
(uint32_t *)BL602_DMA_CH_N_REG(BL602_DMA_SRCADDR_OFFSET,
priv->dma_rxchan),
(uint32_t *)rx_lli, 4);
}
/* Dump DMA register state */
bl602_dmasample(&regs);
bl602_dmadump(&regs, "Initialized DMA");
/* Start channel */
if (rxbuffer != NULL)
{
bl602_dma_channel_start(priv->dma_rxchan);
}
bl602_dma_channel_start(priv->dma_txchan);
/* Dump DMA register state */
bl602_dmasample(&regs);
bl602_dmadump(&regs, "Post Start DMA");
/* Wait for RX and TX to complete. */
nxsem_wait_uninterruptible(&priv->sem_isr_tx);
if (rxbuffer != NULL)
{
nxsem_wait_uninterruptible(&priv->sem_isr_rx);
}
/* Stop channels */
bl602_dma_channel_stop(priv->dma_txchan);
if (rxbuffer != NULL)
{
bl602_dma_channel_stop(priv->dma_rxchan);
}
kmm_free(tx_lli);
if (rx_lli != NULL)
{
kmm_free(rx_lli);
}
return;
}
#endif
/****************************************************************************
* Name: bl602_spi_poll_send
@ -869,6 +1159,7 @@ static uint32_t bl602_spi_poll_send(struct bl602_spi_priv_s *priv,
*
****************************************************************************/
#ifdef CONFIG_BL602_SPI_DMA
static uint32_t bl602_spi_dma_send(struct bl602_spi_priv_s *priv,
uint32_t wd)
{
@ -878,6 +1169,7 @@ static uint32_t bl602_spi_dma_send(struct bl602_spi_priv_s *priv,
return rd;
}
#endif
/****************************************************************************
* Name: bl602_spi_send
@ -898,9 +1190,11 @@ static uint32_t bl602_spi_dma_send(struct bl602_spi_priv_s *priv,
static uint32_t bl602_spi_send(struct spi_dev_s *dev, uint32_t wd)
{
struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)dev;
#ifdef CONFIG_BL602_SPI_DMA
uint32_t rd;
if (priv->dma_chan)
if (priv->dma_txchan >= 0 && priv->dma_rxchan >= 0)
{
rd = bl602_spi_dma_send(priv, wd);
}
@ -910,6 +1204,9 @@ static uint32_t bl602_spi_send(struct spi_dev_s *dev, uint32_t wd)
}
return rd;
#else
return bl602_spi_poll_send(priv, wd);
#endif
}
/****************************************************************************
@ -998,7 +1295,8 @@ static void bl602_spi_exchange(struct spi_dev_s *dev,
{
struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)dev;
if (priv->dma_chan)
#ifdef CONFIG_BL602_SPI_DMA
if (priv->dma_txchan >= 0 && priv->dma_rxchan >= 0)
{
bl602_spi_dma_exchange(priv, txbuffer, rxbuffer, nwords);
}
@ -1006,6 +1304,9 @@ static void bl602_spi_exchange(struct spi_dev_s *dev,
{
bl602_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
}
#else
bl602_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
#endif
}
#ifndef CONFIG_SPI_EXCHANGE
@ -1145,6 +1446,100 @@ static void bl602_swap_spi_0_mosi_with_miso(uint8_t swap)
}
}
#ifdef CONFIG_BL602_SPI_DMA
/****************************************************************************
* Name: bl602_spi_dma_init
*
* Description:
* Initialize BL SPI connection to DMA engine.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* None.
*
****************************************************************************/
void bl602_spi_dma_init(struct spi_dev_s *dev)
{
struct bl602_spi_priv_s *priv = (struct bl602_spi_priv_s *)dev;
#ifdef CONFIG_DEBUG_DMA_INFO
struct bl602_dmaregs_s regs;
#endif
/* NOTE DMA channels are limited on this device and not all SPI devices
* care about the RX side. Consider making the RX channel optional.
*/
/* Request a DMA channel for SPI peripheral */
priv->dma_rxchan = bl602_dma_channel_request(bl602_dma_rx_callback,
(void *)priv);
if (priv->dma_rxchan < 0)
{
spierr("Failed to allocate GDMA channel\n");
DEBUGASSERT(false);
return;
}
priv->dma_txchan = bl602_dma_channel_request(bl602_dma_tx_callback,
(void *)priv);
if (priv->dma_txchan < 0)
{
spierr("Failed to allocate GDMA channel\n");
/* Release the RX channel since we won't be using it. */
bl602_dma_channel_release(priv->dma_rxchan);
priv->dma_rxchan = -1;
DEBUGASSERT(false);
return;
}
/* Configure channels for SPI DMA */
/* Configure channel from SPI to Mem */
modifyreg32(
BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, priv->dma_rxchan),
DMA_C0CONFIG_FLOWCNTRL_MASK | \
DMA_C0CONFIG_DSTPERIPHERAL_MASK | \
DMA_C0CONFIG_SRCPERIPHERAL_MASK,
(BL602_DMA_TRNS_P2M << DMA_C0CONFIG_FLOWCNTRL_SHIFT) | \
(BL602_DMA_REQ_SPI_RX << DMA_C0CONFIG_SRCPERIPHERAL_SHIFT));
/* Configure channel from Mem to SPI */
modifyreg32(
BL602_DMA_CH_N_REG(BL602_DMA_CONFIG_OFFSET, priv->dma_txchan),
DMA_C0CONFIG_FLOWCNTRL_MASK | DMA_C0CONFIG_DSTPERIPHERAL_MASK | \
DMA_C0CONFIG_SRCPERIPHERAL_MASK,
(BL602_DMA_TRNS_M2P << DMA_C0CONFIG_FLOWCNTRL_SHIFT) | \
(BL602_DMA_REQ_SPI_TX << DMA_C0CONFIG_DSTPERIPHERAL_SHIFT));
/* Set FIFO threshold to trigger DMA */
modifyreg32(
BL602_SPI_FIFO_CFG_1,
SPI_FIFO_CFG_1_RX_TH_MASK | SPI_FIFO_CFG_1_TX_TH_MASK,
(0 << SPI_FIFO_CFG_1_RX_TH_SHIFT) | (0 << SPI_FIFO_CFG_1_TX_TH_SHIFT));
/* Enable DMA support */
modifyreg32(BL602_SPI_FIFO_CFG_0, 0,
SPI_FIFO_CFG_0_DMA_RX_EN | SPI_FIFO_CFG_0_DMA_TX_EN);
/* Dump DMA register state */
bl602_dmasample(&regs);
bl602_dmadump(&regs, "Initialized DMA");
}
#endif
/****************************************************************************
* Name: bl602_spi_init
*
@ -1167,6 +1562,8 @@ static void bl602_spi_init(struct spi_dev_s *dev)
/* Initialize the SPI semaphore that enforces mutually exclusive access */
nxsem_init(&priv->exclsem, 0, 1);
nxsem_init(&priv->sem_isr_rx, 0, 0);
nxsem_init(&priv->sem_isr_tx, 0, 0);
bl602_configgpio(BOARD_SPI_CS);
bl602_configgpio(BOARD_SPI_MOSI);
@ -1192,9 +1589,11 @@ static void bl602_spi_init(struct spi_dev_s *dev)
| SPI_CFG_CR_BYTE_INV | SPI_CFG_CR_BIT_INV,
SPI_CFG_CR_DEG_EN);
/* disable rx ignore */
/* Disable rx ignore.
* Enable continuous mode.
*/
modifyreg32(BL602_SPI_CFG, SPI_CFG_CR_RXD_IGNR_EN, 0);
modifyreg32(BL602_SPI_CFG, SPI_CFG_CR_RXD_IGNR_EN, SPI_CFG_CR_M_CONT_EN);
bl602_spi_setfrequency(dev, config->clk_freq);
bl602_spi_setbits(dev, 8);
@ -1204,6 +1603,10 @@ static void bl602_spi_init(struct spi_dev_s *dev)
modifyreg32(BL602_SPI_FIFO_CFG_0, SPI_FIFO_CFG_0_RX_CLR
| SPI_FIFO_CFG_0_TX_CLR, 0);
#ifdef CONFIG_BL602_SPI_DMA
bl602_spi_dma_init(dev);
#endif
}
/****************************************************************************
@ -1230,7 +1633,8 @@ static void bl602_spi_deinit(struct spi_dev_s *dev)
priv->actual = 0;
priv->mode = SPIDEV_MODE0;
priv->nbits = 0;
priv->dma_chan = 0;
priv->dma_txchan = -1;
priv->dma_rxchan = -1;
}
/****************************************************************************
@ -1317,6 +1721,8 @@ int bl602_spibus_uninitialize(struct spi_dev_s *dev)
bl602_spi_deinit(dev);
nxsem_destroy(&priv->exclsem);
nxsem_destroy(&priv->sem_isr_rx);
nxsem_destroy(&priv->sem_isr_tx);
return OK;
}

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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