arch/arm/src/max326xx: Finish DMA implementation. Clean up compile issues when DMA, GPIO interrupts are enabled.
This commit is contained in:
parent
7a45fc6f1c
commit
b9903dc8c8
@ -109,7 +109,7 @@
|
||||
|
||||
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
#warning Missing logic
|
||||
#else
|
||||
# define MAX326_IRQ_NPININT 0
|
||||
|
@ -84,7 +84,7 @@
|
||||
|
||||
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
/* Up to 14 pins are available as interrupt sources, depending on the MAX32660 package */
|
||||
|
||||
# define MAX326_IRQ_P0_0 (MAX326_IRQ_NEXTINT + 0)
|
||||
|
@ -413,6 +413,6 @@ config MAX326XX_DMA
|
||||
default n
|
||||
depends on MAX326XX_HAVE_DMA
|
||||
|
||||
config MAX326_GPIOIRQ
|
||||
config MAX326XX_GPIOIRQ
|
||||
bool "GPIO Interrupt Support"
|
||||
default n
|
||||
|
@ -89,7 +89,7 @@
|
||||
|
||||
/* DMA Channel Registers */
|
||||
|
||||
#define MAX326_DMACH_OFFSET(n) (0x0100 + )(n) << 5))
|
||||
#define MAX326_DMACH_OFFSET(n) (0x0100 + ((unsigned int)(n) << 5))
|
||||
#define MAX326_DMACH0_OFFSET 0x0100
|
||||
#define MAX326_DMACH1_OFFSET 0x0120
|
||||
#define MAX326_DMACH2_OFFSET 0x0140
|
||||
@ -151,7 +151,8 @@
|
||||
# define DMACH_CFG_PRI_MEDLO (2 << DMACH_CFG_PRI_SHIFT)
|
||||
# define DMACH_CFG_PRI_MEDHI (1 << DMACH_CFG_PRI_SHIFT)
|
||||
# define DMACH_CFG_PRI_HI (0 << DMACH_CFG_PRI_SHIFT)
|
||||
#define DMACH_CFG_REQSEL_SHIFT (4) /* Bits 4-9: Request Select */
|
||||
#define DMACH_CFG_REQSEL_SHIFT (4) /* Bits 4-9: Request Select
|
||||
* See values below */
|
||||
#define DMACH_CFG_REQSEL_MASK (0x3f << DMACH_CFG_REQSEL_SHIFT)
|
||||
# define DMACH_CFG_REQSEL(n) ((uint32_t)(n) << DMACH_CFG_REQSEL_SHIFT)
|
||||
#define DMACH_CFG_REQWAIT (1 << 10) /* Bit 10: Request Wait Enable */
|
||||
@ -174,6 +175,7 @@
|
||||
# define DMACH_CFG_PSSEL_DIV64K (2 << DMACH_CFG_PSSEL_SHIFT) /* fhclk / 64K */
|
||||
# define DMACH_CFG_PSSEL_DIV16M (3 << DMACH_CFG_PSSEL_SHIFT) /* fhclk / 16M */
|
||||
#define DMACH_CFG_SRCWD_SHIFT (16) /* Bits 16-17: Source Width */
|
||||
#define DMACH_CFG_SRCWD_MASK (3 << DMACH_CFG_SRCWD_SHIFT)
|
||||
# define DMACH_CFG_SRCWD_1BYTE (0 << DMACH_CFG_SRCWD_SHIFT)
|
||||
# define DMACH_CFG_SRCWD_2BYTES (1 << DMACH_CFG_SRCWD_SHIFT)
|
||||
# define DMACH_CFG_SRCWD_4BYTES (2 << DMACH_CFG_SRCWD_SHIFT)
|
||||
@ -193,6 +195,53 @@
|
||||
* Interrupt Enable */
|
||||
#define DMACH_CFG_CTZIEN (1 << 31) /* Bit 31: CTZ Interrupt Enable */
|
||||
|
||||
/* Values for the CFG register Request Select field */
|
||||
|
||||
#define DMACH_REQSEL_MEMTOMEM 0x00
|
||||
#define DMACH_REQSEL_SPI0RX 0x01
|
||||
#define DMACH_REQSEL_SPI1RX 0x02
|
||||
#define DMACH_REQSEL_SPI2RX 0x03
|
||||
#define DMACH_REQSEL_UART0RX 0x04
|
||||
#define DMACH_REQSEL_UART1RX 0x05
|
||||
#define DMACH_REQSEL_I2C0RX 0x07
|
||||
#define DMACH_REQSEL_I2C1RX 0x08
|
||||
#define DMACH_REQSEL_ADC 0x09
|
||||
#define DMACH_REQSEL_UART2RX 0x0e
|
||||
#define DMACH_REQSEL_SPI3RX 0x0f
|
||||
#define DMACH_REQSEL_SPI_MSS0RX 0x10
|
||||
#define DMACH_REQSEL_USBRXEP1 0x11
|
||||
#define DMACH_REQSEL_USBRXEP2 0x12
|
||||
#define DMACH_REQSEL_USBRXEP3 0x13
|
||||
#define DMACH_REQSEL_USBRXEP4 0x14
|
||||
#define DMACH_REQSEL_USBRXEP5 0x15
|
||||
#define DMACH_REQSEL_USBRXEP6 0x16
|
||||
#define DMACH_REQSEL_USBRXEP7 0x17
|
||||
#define DMACH_REQSEL_USBRXEP8 0x18
|
||||
#define DMACH_REQSEL_USBRXEP9 0x19
|
||||
#define DMACH_REQSEL_USBRXEP10 0x1a
|
||||
#define DMACH_REQSEL_USBRXEP11 0x1b
|
||||
#define DMACH_REQSEL_SPI0TX 0x21
|
||||
#define DMACH_REQSEL_SPI1TX 0x22
|
||||
#define DMACH_REQSEL_SPI2TX 0x23
|
||||
#define DMACH_REQSEL_UART0TX 0x24
|
||||
#define DMACH_REQSEL_UART1TX 0x25
|
||||
#define DMACH_REQSEL_I2C0TX 0x27
|
||||
#define DMACH_REQSEL_I2C1TX 0x28
|
||||
#define DMACH_REQSEL_UART2TX 0x2e
|
||||
#define DMACH_REQSEL_SPI3TX 0x2f
|
||||
#define DMACH_REQSEL_SPI_MSS0TX 0x30
|
||||
#define DMACH_REQSEL_USBTXEP1 0x31
|
||||
#define DMACH_REQSEL_USBTXEP2 0x32
|
||||
#define DMACH_REQSEL_USBTXEP3 0x33
|
||||
#define DMACH_REQSEL_USBTXEP4 0x34
|
||||
#define DMACH_REQSEL_USBTXEP5 0x35
|
||||
#define DMACH_REQSEL_USBTXEP6 0x36
|
||||
#define DMACH_REQSEL_USBTXEP7 0x37
|
||||
#define DMACH_REQSEL_USBTXEP8 0x38
|
||||
#define DMACH_REQSEL_USBTXEP9 0x39
|
||||
#define DMACH_REQSEL_USBTXEP10 0x3a
|
||||
#define DMACH_REQSEL_USBTXEP11 0x3b
|
||||
|
||||
/* DMA Channel Status Register */
|
||||
|
||||
#define DMACH_STAT_CHST (1 << 0) /* Bit 0: Channel Status */
|
||||
|
@ -40,10 +40,10 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip/max326_icc.h"
|
||||
#include "max326_periphclks.h"
|
||||
#include "max326_icc.h"
|
||||
|
||||
|
@ -439,7 +439,7 @@ void up_disable_irq(int irq)
|
||||
uint32_t regval;
|
||||
uint32_t bit;
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
/* Handle "fake" GPIO irq */
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
@ -485,12 +485,12 @@ void up_enable_irq(int irq)
|
||||
uint32_t regval;
|
||||
uint32_t bit;
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
/* Handle "fake" GPIO irq */
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
{
|
||||
max326_gpio_irqensable(irq);
|
||||
max326_gpio_irqenable(irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -569,7 +569,7 @@ int up_prioritize_irq(int irq, int priority)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef CONFIG_MAX326_GPIOIRQ
|
||||
#ifndef CONFIG_MAX326XX_GPIOIRQ
|
||||
DEBUGPANIC();
|
||||
#endif
|
||||
return;
|
||||
|
@ -39,30 +39,180 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "max326_dma.h"
|
||||
|
||||
#ifdef CONFIG_MAX326_DMA
|
||||
#ifdef CONFIG_MAX326XX_DMA
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#define MAX326_IRQ_DMA(n) (MAX326_IRQ_DMA0 + (n))
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes state of a DMA channel */
|
||||
/* TODO: Additional reload values for chains > 2 could be held here */
|
||||
|
||||
struct max326_dmach_s
|
||||
{
|
||||
uint8_t chno; /* Channel number, 0..(MAX326_DMA_NCHAN - 1) */
|
||||
bool inuse; /* True: DMA channel is in-use */
|
||||
bool reload; /* True: Buffer chained, reload needed */
|
||||
dma_callback_t cb; /* DMA complete callback function */
|
||||
void *arg; /* Argument provided with the DMA callback */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
struct max326_dmach_s g_max326_dmach[MAX326_DMA_NCHAN];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_dmach_terminate
|
||||
*
|
||||
* Description:
|
||||
* Terminate the DMA and perform the DMA complete callback.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void max326_dma_terminate(struct max326_dmach_s *dmach, int result)
|
||||
{
|
||||
DEBUGASSERT(dmach != NULL && dmach->cb != NULL);
|
||||
uintptr_t base;
|
||||
|
||||
/* Disable channel interrupts at the NVIC */
|
||||
|
||||
up_disable_irq(MAX326_IRQ_DMA(dmach->chno));
|
||||
|
||||
/* Enable channel interrupts at the DMA controller */
|
||||
|
||||
modifyreg32(MAX326_DMA_INTEN_OFFSET, 1 << dmach->chno, 0);
|
||||
|
||||
/* Disable the channel. */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
putreg32(0, base + MAX326_DMACH_CFG_OFFSET);
|
||||
|
||||
/* Perform the callback */
|
||||
|
||||
dmach->cb((DMA_HANDLE)dmach, dmach->arg, result);
|
||||
|
||||
/* Make sure that no further callbacks are performed */
|
||||
|
||||
dmach->cb = NULL;
|
||||
dmach->arg = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_dmach_interrupt
|
||||
*
|
||||
* Description:
|
||||
* DMA channel interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int max326_dmach_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)arg;
|
||||
uintptr_t base;
|
||||
uint32_t stat;
|
||||
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse);
|
||||
|
||||
/* Get and clear the DMA status */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
stat = getreg32(base + MAX326_DMACH_STAT_OFFSET);
|
||||
putreg32(stat, base + MAX326_DMACH_STAT_OFFSET);
|
||||
|
||||
/* Verify that an interrupt is pending (how could it not be?) */
|
||||
|
||||
DEBUGASSERT((stat & DMACH_STAT_IPEND) != 0);
|
||||
if ((stat & DMACH_STAT_IPEND) == 0)
|
||||
{
|
||||
dmaerr("Interrupt with nothing pending: %04x\n", stat);
|
||||
return OK;
|
||||
}
|
||||
|
||||
DEBUGASSERT((stat & (DMACH_STAT_CTZST | DMACH_STAT_BUSERR |
|
||||
DMACH_STAT_TOST)) != 0);
|
||||
|
||||
/* Check for DMA errors. */
|
||||
|
||||
if ((stat & (DMACH_STAT_BUSERR | DMACH_STAT_TOST)) != 0)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Map the error to an errno value */
|
||||
|
||||
if ((stat & DMACH_STAT_BUSERR) != 0)
|
||||
{
|
||||
/* A bus error occurred */
|
||||
|
||||
result = -EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, a timeout occurred */
|
||||
|
||||
result = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
max326_dma_terminate(dmach, result);
|
||||
}
|
||||
|
||||
/* The DMA status register indicates that the CTZ and /or reload events
|
||||
* occurred. In the case of a reload, the channel status bit (CHST) will
|
||||
* be set indicating that the DMA is now busy with the second DMA transfer
|
||||
* defined in the reload registers. If CHST = 0, then the initial and
|
||||
* second DMA transfers have completed. If there are additional buffers to
|
||||
* chain, the interrupt service routine initializes the SRCRLD, DSTRLD,
|
||||
* and CNTRLD registers and sets the RLDEN bit in the CNTRLD register. The
|
||||
* interrupt service routine does not write to the CFG, SRC, DST, and CNT
|
||||
* registers, just the reload registers.
|
||||
*/
|
||||
|
||||
if ((stat & DMACH_STAT_CHST) != 0)
|
||||
{
|
||||
/* We must be on the buffer of a chained DMA */
|
||||
/* TODO: Add software logic to manage more than two DMA buffers in
|
||||
* the chain.
|
||||
*/
|
||||
|
||||
/* We don't really need to do anything; the RLDEN bit is automatically
|
||||
* disabled after the reload occurs. But let's leave some bread
|
||||
* crumbs so that we will know we have been this way.
|
||||
*/
|
||||
|
||||
putreg32(0, base + MAX326_DMACH_SRCRLD_OFFSET);
|
||||
putreg32(0, base + MAX326_DMACH_DSTRLD_OFFSET);
|
||||
putreg32(0, base + MAX326_DMACH_CNTRLD_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, the DMA completed successfully. */
|
||||
|
||||
max326_dma_terminate(dmach, OK);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -81,6 +231,23 @@
|
||||
|
||||
void weak_function up_dma_initialize(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Initialize each DMA channel */
|
||||
|
||||
for (i = 0; i < MAX326_DMA_NCHAN; i++)
|
||||
{
|
||||
struct max326_dmach_s *dmach = &g_max326_dmach[i];
|
||||
|
||||
/* Initialize the state structure (assuming that it is already zeroed) */
|
||||
|
||||
dmach->chno = i;
|
||||
|
||||
/* Attach the DMA channel interrupt handler */
|
||||
|
||||
DEBUGVERIFY(irq_attach(MAX326_IRQ_DMA(i), max326_dmach_interrupt,
|
||||
dmach));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -97,6 +264,32 @@ void weak_function up_dma_initialize(void)
|
||||
|
||||
DMA_HANDLE max326_dma_channel(void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int i;
|
||||
|
||||
/* Since there are only 4 DMA channel, no point in any exotic channel
|
||||
* allocation. Just check each channel until a free one is found (on not).
|
||||
*/
|
||||
|
||||
flags = spin_lock_irqsave();
|
||||
for (i = 0; i < 0; i++)
|
||||
{
|
||||
struct max326_dmach_s *dmach = &g_max326_dmach[i];
|
||||
|
||||
/* Check if this channel is available */
|
||||
|
||||
if (!dmach->inuse)
|
||||
{
|
||||
/* No.. allocate this channel */
|
||||
|
||||
dmach->inuse = true;
|
||||
spin_unlock_irqrestore(flags);
|
||||
return (DMA_HANDLE)dmach;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(flags);
|
||||
return (DMA_HANDLE)NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -114,6 +307,10 @@ DMA_HANDLE max326_dma_channel(void)
|
||||
|
||||
void max326_dma_free(DMA_HANDLE handle)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse);
|
||||
dmach->inuse = false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -126,15 +323,57 @@ void max326_dma_free(DMA_HANDLE handle)
|
||||
* following fields need be provided however. The DMA logic will handle
|
||||
* the rest.
|
||||
*
|
||||
* PRI DMA priority
|
||||
* REQSEL Request Select
|
||||
* REQWAIT Request Wait Enable
|
||||
* TOSEL Time-Out Select
|
||||
* PSSEL Pre-Scale Select
|
||||
* SRCWD Source Width
|
||||
* SRCINC Source Increment Enable
|
||||
* DSTWD Destination Width
|
||||
* DSTINC Destination Increment Enable
|
||||
* BRST Burst Size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int max326_dma_setup(DMA_HANDLE handle, uint32_t cfg, uint32_t saddr,
|
||||
uint32_t daddr, size_t nbytes)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
uintptr_t base;
|
||||
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse);
|
||||
DEBUGASSERT(nbytes > 0 && nbytes < (1 << 24));
|
||||
|
||||
/* Set up the DMA channel registers */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
cfg &= (DMACH_CFG_PRI_MASK | DMACH_CFG_REQSEL_MASK | DMACH_CFG_REQWAIT |
|
||||
DMACH_CFG_TOSEL_MASK | DMACH_CFG_PSSEL_MASK |
|
||||
DMACH_CFG_SRCWD_MASK | DMACH_CFG_SRCINC | DMACH_CFG_DSTWD_MASK |
|
||||
DMACH_CFG_DSTINC | DMACH_CFG_BRST_MASK);
|
||||
putreg32(cfg, base + MAX326_DMACH_CFG_OFFSET);
|
||||
|
||||
putreg32(saddr, base + MAX326_DMACH_SRC_OFFSET);
|
||||
putreg32(daddr, base + MAX326_DMACH_DST_OFFSET);
|
||||
putreg32(nbytes, base + MAX326_DMACH_CNT_OFFSET);
|
||||
|
||||
/* No reload (yet) */
|
||||
|
||||
putreg32(0, base + MAX326_DMACH_SRCRLD_OFFSET);
|
||||
putreg32(0, base + MAX326_DMACH_DSTRLD_OFFSET);
|
||||
putreg32(0, base + MAX326_DMACH_CNTRLD_OFFSET);
|
||||
|
||||
/* Setup the DMA channel state */
|
||||
|
||||
dmach->reload = false;
|
||||
dmach->cb = NULL;
|
||||
dmach->arg = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_dma_setup
|
||||
* Name: max326_dma_append
|
||||
*
|
||||
* Description:
|
||||
* Append one buffer to the DMA chain. max326_dma_setup() should have
|
||||
@ -147,9 +386,25 @@ int max326_dma_setup(DMA_HANDLE handle, uint32_t cfg, uint32_t saddr,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int max326_dma_setup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes)
|
||||
int max326_dma_append(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
uintptr_t base;
|
||||
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse && !dmach->reload);
|
||||
|
||||
/* Set up the DMA channel reload registers */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
putreg32(saddr, base + MAX326_DMACH_SRCRLD_OFFSET);
|
||||
putreg32(daddr, base + MAX326_DMACH_DSTRLD_OFFSET);
|
||||
putreg32(nbytes, base + MAX326_DMACH_CNTRLD_OFFSET);
|
||||
|
||||
/* Setup the DMA channel state */
|
||||
|
||||
dmach->reload = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -162,6 +417,38 @@ int max326_dma_setup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
|
||||
int max326_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
uintptr_t base;
|
||||
uint32_t cfg;
|
||||
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse);
|
||||
|
||||
/* Enable interrupts and reload (if appropriate) */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
cfg = getreg32(base + MAX326_DMACH_CFG_OFFSET);
|
||||
cfg |= (DMACH_CFG_CHDIEN | DMACH_CFG_CTZIEN);
|
||||
|
||||
if (dmach->reload)
|
||||
{
|
||||
cfg |= DMACH_CFG_RLDEN;
|
||||
}
|
||||
|
||||
putreg32(cfg, base + MAX326_DMACH_CFG_OFFSET);
|
||||
|
||||
/* Enable channel interrupts at the DMA controller */
|
||||
|
||||
modifyreg32(MAX326_DMA_INTEN_OFFSET, 0, 1 << dmach->chno);
|
||||
|
||||
/* Enable the channel and start the DMA */
|
||||
|
||||
cfg |= DMACH_CFG_CHEN;
|
||||
putreg32(cfg, base + MAX326_DMACH_CFG_OFFSET);
|
||||
|
||||
/* Enable channel interrupts at the NVIC */
|
||||
|
||||
up_enable_irq(MAX326_IRQ_DMA(dmach->chno));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -176,6 +463,8 @@ int max326_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
|
||||
void max326_dmastop(DMA_HANDLE handle)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
max326_dma_terminate(dmach, -ECANCELED);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -189,6 +478,28 @@ void max326_dmastop(DMA_HANDLE handle)
|
||||
#ifdef CONFIG_DEBUG_DMA_INFO
|
||||
void max326_dmasample(DMA_HANDLE handle, struct max326_dmaregs_s *regs)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
uintptr_t base;
|
||||
uint32_t cfg;
|
||||
|
||||
DEBUGASSERT(dmach != NULL);
|
||||
|
||||
/* Global Registers */
|
||||
|
||||
regs->inten = getreg32(MAX326_DMA_INTEN);
|
||||
regs->intfl = getreg32(MAX326_DMA_INTRL);
|
||||
|
||||
/* Channel Registers */
|
||||
|
||||
base = MAX326_DMACH_BASE(dmach->chno);
|
||||
regs->cfg = getreg32(base + MAX326_DMACH_CFG_OFFSET);
|
||||
regs->stat = getreg32(base + MAX326_DMACH_STAT_OFFSET);
|
||||
regs->src = getreg32(base + MAX326_DMACH_SRC_OFFSET);
|
||||
regs->dst = getreg32(base + MAX326_DMACH_DST_OFFSET);
|
||||
regs->cnt = getreg32(base + MAX326_DMACH_CNT_OFFSET);
|
||||
regs->srcrld = getreg32(base + MAX326_DMACH_SRCRLD_OFFSET);
|
||||
regs->dstrld = getreg32(base + MAX326_DMACH_DSTRLD_OFFSET);
|
||||
regs->cntrld = getreg32(base + MAX326_DMACH_CNTRLD_OFFSET);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -204,7 +515,28 @@ void max326_dmasample(DMA_HANDLE handle, struct max326_dmaregs_s *regs)
|
||||
void max326_dmadump(DMA_HANDLE handle, const struct max326_dmaregs_s *regs,
|
||||
const char *msg)
|
||||
{
|
||||
struct max326_dmach_s *dmach = (struct max326_dmach_s *)handle;
|
||||
|
||||
DEBUGASSERT(dmach != NULL);
|
||||
|
||||
/* Global Registers */
|
||||
|
||||
dmainfo("DMA Global Registers: %s\n", msg);
|
||||
dmainfo(" INTEN: %04x\n", regs->inten);
|
||||
dmainfo(" INTFL: %04x\n", regs->intfl);
|
||||
|
||||
/* Channel Registers */
|
||||
|
||||
dmainfo("DMA Channel %u Registers:\n", dmach->chno);
|
||||
dmainfo(" CFG: %04x\n", regs->cfg);
|
||||
dmainfo(" STAT: %04x\n", regs->stat);
|
||||
dmainfo(" SRC: %04x\n", regs->src);
|
||||
dmainfo(" DST: %04x\n", regs->dst);
|
||||
dmainfo(" CNT: %04x\n", regs->cnt);
|
||||
dmainfo(" SRCRLD: %04x\n", regs->srcrld);
|
||||
dmainfo(" DSTRLD: %04x\n", regs->dstrld);
|
||||
dmainfo(" CNTRLD: %04x\n", regs->cntrld);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_MAX326_DMA */
|
||||
#endif /* CONFIG_MAX326XX_DMA */
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
@ -144,13 +145,24 @@ void max326_dma_free(DMA_HANDLE handle);
|
||||
* following fields need be provided however. The DMA logic will handle
|
||||
* the rest.
|
||||
*
|
||||
* CFG DMA priority
|
||||
* REQSEL Request Select
|
||||
* REQWAIT Request Wait Enable
|
||||
* TOSEL Time-Out Select
|
||||
* PSSEL Pre-Scale Select
|
||||
* SRCWD Source Width
|
||||
* SRCINC Source Increment Enable
|
||||
* DSTWD Destination Width
|
||||
* DSTINC Destination Increment Enable
|
||||
* BRST Burst Size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int max326_dma_setup(DMA_HANDLE handle, uint32_t cfg, uint32_t saddr,
|
||||
uint32_t daddr, size_t nbytes);
|
||||
uint32_t daddr, size_t nbytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_dma_setup
|
||||
* Name: max326_dma_append
|
||||
*
|
||||
* Description:
|
||||
* Append one buffer to the DMA chain. max326_dma_setup() should have
|
||||
@ -163,8 +175,8 @@ int max326_dma_setup(DMA_HANDLE handle, uint32_t cfg, uint32_t saddr,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int max326_dma_setup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes);
|
||||
int max326_dma_append(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_dmastart
|
||||
|
@ -385,7 +385,7 @@ int max326_gpio_config(max326_pinset_t pinset)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
/* Configure the interrupt */
|
||||
|
||||
if (GPIO_IS_INTR(pinset))
|
||||
|
@ -41,34 +41,31 @@
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "max326_gpio.h"
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_gpio_irqinitialize
|
||||
* Name: max326_gpio0_interrupt
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support interrupting GPIO pins. This function is
|
||||
* called by the OS initialization logic and is not a user interface.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called early in the boot-up sequence
|
||||
* GPIO0 pin interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int max326_gpio0_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
uint32_t pending;
|
||||
int 0;
|
||||
int i;
|
||||
|
||||
/* Get the pending interrupt set */
|
||||
|
||||
@ -86,6 +83,8 @@ static int max326_gpio0_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
irq_dispatch(MAX326_IRQ_GPIO1ST + i, context);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -104,7 +103,7 @@ static int max326_gpio0_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void max326_gpio_irqinitialize(void);
|
||||
void max326_gpio_irqinitialize(void)
|
||||
{
|
||||
/* Attach the GPIO0 interrupt handler and enable interrupts */
|
||||
|
||||
@ -181,17 +180,17 @@ void max326_gpio_irqconfig(max326_pinset_t cfgset)
|
||||
regval = getreg32(MAX326_GPIO0_INTMODE);
|
||||
regval &= ~pinmask;
|
||||
regval |= intmode;
|
||||
putreg32(regval, MAX326_GPIO0_INTMODE)
|
||||
putreg32(regval, MAX326_GPIO0_INTMODE);
|
||||
|
||||
regval = getreg32(MAX326_GPIO0_INTPOL);
|
||||
regval &= ~pinmask;
|
||||
regval |= intpol;
|
||||
putreg32(regval, MAX326_GPIO0_INTPOL)
|
||||
putreg32(regval, MAX326_GPIO0_INTPOL);
|
||||
|
||||
regval = getreg32(MAX326_GPIO0_INTDUALEDGE);
|
||||
regval &= ~pinmask;
|
||||
regval |= intdual;
|
||||
putreg32(regval, MAX326_GPIO0_INTDUALEDGE)
|
||||
putreg32(regval, MAX326_GPIO0_INTDUALEDGE);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
@ -214,7 +213,7 @@ void max326_gpio_irqdisable(int irq)
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
{
|
||||
pin = irq - MAX326_IRQ_GPIO1ST
|
||||
pin = irq - MAX326_IRQ_GPIO1ST;
|
||||
|
||||
/* Modification of registers must be atomic */
|
||||
|
||||
@ -242,7 +241,7 @@ void max326_gpio_irqenable(int irq)
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
{
|
||||
pin = irq - MAX326_IRQ_GPIO1ST
|
||||
pin = irq - MAX326_IRQ_GPIO1ST;
|
||||
|
||||
/* Modification of registers must be atomic */
|
||||
|
||||
@ -250,4 +249,4 @@ void max326_gpio_irqenable(int irq)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MAX326_GPIOIRQ */
|
||||
#endif /* CONFIG_MAX326XX_GPIOIRQ */
|
||||
|
@ -44,8 +44,9 @@
|
||||
|
||||
/* Standard DMA is only available for the MAX32660 */
|
||||
|
||||
#ifdef (CONFIG_ARCH_FAMILY_MAX32660)
|
||||
#ifdef CONFIG_ARCH_FAMILY_MAX32660
|
||||
# include "chip/max326_dma.h"
|
||||
# include "max32660/max32660_dma.h"
|
||||
#ednif
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_MAX436XX_MAX326_DMA_H */
|
||||
|
@ -91,7 +91,7 @@ extern "C"
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
void max326_gpio_irqinitialize(void);
|
||||
#endif
|
||||
|
||||
@ -119,7 +119,7 @@ int max326_gpio_config(max326_pinset_t pinset);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
void max326_gpio_irqconfig(max326_pinset_t pinset);
|
||||
#endif
|
||||
|
||||
@ -152,7 +152,7 @@ bool max326_gpio_read(max326_pinset_t pinset);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
void max326_gpio_irqdisable(int irq);
|
||||
#endif
|
||||
|
||||
@ -165,7 +165,7 @@ void max326_gpio_irqdisable(int irq);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#ifdef CONFIG_MAX326XX_GPIOIRQ
|
||||
void max326_gpio_irqenable(int irq);
|
||||
#endif
|
||||
|
||||
|
@ -41,6 +41,9 @@
|
||||
************************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "chip/max326_icc.h"
|
||||
|
||||
/************************************************************************************
|
||||
* Public Function Prototypes
|
||||
|
Loading…
Reference in New Issue
Block a user