From 4e32861c3cd1f1d2996eb9505c3d7903e8175792 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 11 Feb 2018 16:42:37 -0600 Subject: [PATCH] Changes from review of last PR + some updated comments. --- arch/arm/src/samdl/Kconfig | 36 ++-- arch/arm/src/samdl/sam_dmac.c | 9 +- arch/arm/src/samdl/sam_spi.c | 239 ++++++++++++++------------ configs/flipnclick-pic32mz/README.txt | 8 + configs/flipnclick-sam3x/README.txt | 4 +- 5 files changed, 159 insertions(+), 137 deletions(-) diff --git a/arch/arm/src/samdl/Kconfig b/arch/arm/src/samdl/Kconfig index fc76c2290b..3026bc9fcb 100644 --- a/arch/arm/src/samdl/Kconfig +++ b/arch/arm/src/samdl/Kconfig @@ -488,20 +488,6 @@ config SAMDL_DMAC select ARCH_DMA depends on SAMDL_HAVE_DMAC && EXPERIMENTAL -if SAMDL_DMAC && EXPERIMENTAL - -menu "DMA options" - -config SAMDL_SPI_DMA - bool "SPI DMA" - default n - depends on (SAMDL_HAVE_SPI) - ---help--- - Use DMA for SPI SERCOM peripherals. -endmenu - -endif - config SAMDL_EVSYS bool "Event System" default n @@ -734,7 +720,15 @@ config SAMDL_HAVE_SPI bool select SPI -if SAMDL_HAVE_SPI +menu "SPI options" + depends on SAMDL_HAVE_SPI + +config SAMDL_SPI_DMA + bool "SPI DMA" + default n + depends on SAMDL_DMAC && EXPERIMENTAL + ---help--- + Use DMA for SPI SERCOM peripherals. config SAMDL_SPI_REGDEBUG bool "SPI register-Level Debug" @@ -743,13 +737,14 @@ config SAMDL_SPI_REGDEBUG ---help--- Enable very low-level register access debug. Depends on DEBUG_SPI. -endif # SAMDL_HAVE_SPI +endmenu # SPI options config SAMDL_HAVE_I2C bool select I2C -if SAMDL_HAVE_I2C +menu "I2C options" + depends on SAMDL_HAVE_I2C config SAMDL_I2C_REGDEBUG bool "I2C register-Level Debug" @@ -758,9 +753,10 @@ config SAMDL_I2C_REGDEBUG ---help--- Enable very low-level register access debug. Depends on DEBUG_I2C. -endif # SAMDL_HAVE_I2C +endmenu # I2C options -if SAMDL_HAVE_USB +menu "USB options" + depends on SAMDL_HAVE_USB config SAMDL_USB_ENABLE_PPEP bool "Enable Ping-Pong Endpoints" @@ -780,5 +776,5 @@ config SAMDL_USB_REGDEBUG Enable very low-level register access debug. Depends on CONFIG_DEBUG_USB_INFO. -endif # SAMDL_HAVE_USB +endmenu # USB options diff --git a/arch/arm/src/samdl/sam_dmac.c b/arch/arm/src/samdl/sam_dmac.c index 2f1f88dadb..0b354a0390 100644 --- a/arch/arm/src/samdl/sam_dmac.c +++ b/arch/arm/src/samdl/sam_dmac.c @@ -145,8 +145,7 @@ static sem_t g_dsem; static struct sam_dmach_s g_dmach[SAMDL_NDMACHAN]; -/* - * NOTE: Using the same address as the base descriptors for writeback descriptors +/* NOTE: Using the same address as the base descriptors for writeback descriptors * causes TERR and FERR interrupts to be raised immediately after starting DMA. * This was tested on SAMD21G18A, and it would appear that the writeback * buffer must be located at a different memory address. @@ -295,7 +294,6 @@ static int sam_dmainterrupt(int irq, void *context, FAR void *arg) unsigned int chndx; uint16_t intpend; - /* Process all pending channel interrupts */ while ((intpend = getreg16(SAM_DMAC_INTPEND)) != 0) @@ -404,7 +402,6 @@ static struct dma_desc_s *sam_alloc_desc(struct sam_dmach_s *dmach) /* Yes, return a pointer to the base descriptor */ desc->srcaddr = (uint32_t)-1; /* Any non-zero value */ - return desc; } #if CONFIG_SAMDL_DMAC_NDESC > 0 @@ -419,7 +416,6 @@ static struct dma_desc_s *sam_alloc_desc(struct sam_dmach_s *dmach) sam_takedsem(); - /* Examine each list entry to find an available one -- i.e., one * with srcaddr == 0. That srcaddr field is set to zero by the DMA * transfer complete interrupt handler. The following should be safe @@ -574,11 +570,9 @@ static void sam_free_desc(struct sam_dmach_s *dmach) next = (struct dma_desc_s *)desc->descaddr; memset(desc, 0, sizeof(struct dma_desc_s)); - sam_givedsem(); } #endif - } /**************************************************************************** @@ -814,7 +808,6 @@ void weak_function up_dmainitialize(void) /* Initialize global semaphores */ nxsem_init(&g_chsem, 0, 1); - #if CONFIG_SAMDL_DMAC_NDESC > 0 nxsem_init(&g_dsem, 0, CONFIG_SAMDL_DMAC_NDESC); #endif diff --git a/arch/arm/src/samdl/sam_spi.c b/arch/arm/src/samdl/sam_spi.c index 5ee4f10d31..ab75f1f4b3 100644 --- a/arch/arm/src/samdl/sam_spi.c +++ b/arch/arm/src/samdl/sam_spi.c @@ -70,7 +70,7 @@ #include "sam_spi.h" #ifdef CONFIG_SAMDL_SPI_DMA -#include "sam_dmac.h" +# include "sam_dmac.h" #endif #include @@ -181,7 +181,7 @@ static void spi_dumpregs(struct sam_spidev_s *priv, const char *msg); /* Interrupt handling */ #if 0 /* Not used */ -static int spi_interrupt(int irq, void *context, FAR void *arg); +static int spi_interrupt(int irq, void *context, FAR void *arg); #endif /* SPI methods */ @@ -240,24 +240,24 @@ static const struct spi_ops_s g_spi0ops = static struct sam_spidev_s g_spi0dev = { - .ops = &g_spi0ops, - .sercom = 0, + .ops = &g_spi0ops, + .sercom = 0, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM0, + .irq = SAM_IRQ_SERCOM0, #endif - .gclkgen = BOARD_SERCOM0_GCLKGEN, - .slowgen = BOARD_SERCOM0_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM0_PINMAP_PAD0, - .pad1 = BOARD_SERCOM0_PINMAP_PAD1, - .pad2 = BOARD_SERCOM0_PINMAP_PAD2, - .pad3 = BOARD_SERCOM0_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM0_MUXCONFIG, - .srcfreq = BOARD_SERCOM0_FREQUENCY, - .base = SAM_SERCOM0_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM0_GCLKGEN, + .slowgen = BOARD_SERCOM0_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM0_PINMAP_PAD0, + .pad1 = BOARD_SERCOM0_PINMAP_PAD1, + .pad2 = BOARD_SERCOM0_PINMAP_PAD2, + .pad3 = BOARD_SERCOM0_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM0_MUXCONFIG, + .srcfreq = BOARD_SERCOM0_FREQUENCY, + .base = SAM_SERCOM0_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM0_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM0_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM0_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM0_RX, #endif }; #endif @@ -290,24 +290,24 @@ static const struct spi_ops_s g_spi1ops = static struct sam_spidev_s g_spi1dev = { - .ops = &g_spi1ops, - .sercom = 1, + .ops = &g_spi1ops, + .sercom = 1, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM1, + .irq = SAM_IRQ_SERCOM1, #endif - .gclkgen = BOARD_SERCOM1_GCLKGEN, - .slowgen = BOARD_SERCOM1_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM1_PINMAP_PAD0, - .pad1 = BOARD_SERCOM1_PINMAP_PAD1, - .pad2 = BOARD_SERCOM1_PINMAP_PAD2, - .pad3 = BOARD_SERCOM1_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM1_MUXCONFIG, - .srcfreq = BOARD_SERCOM1_FREQUENCY, - .base = SAM_SERCOM1_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM1_GCLKGEN, + .slowgen = BOARD_SERCOM1_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM1_PINMAP_PAD0, + .pad1 = BOARD_SERCOM1_PINMAP_PAD1, + .pad2 = BOARD_SERCOM1_PINMAP_PAD2, + .pad3 = BOARD_SERCOM1_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM1_MUXCONFIG, + .srcfreq = BOARD_SERCOM1_FREQUENCY, + .base = SAM_SERCOM1_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM1_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM1_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM1_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM1_RX, #endif }; #endif @@ -340,24 +340,24 @@ static const struct spi_ops_s g_spi2ops = static struct sam_spidev_s g_spi2dev = { - .ops = &g_spi2ops, - .sercom = 2, + .ops = &g_spi2ops, + .sercom = 2, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM2, + .irq = SAM_IRQ_SERCOM2, #endif - .gclkgen = BOARD_SERCOM2_GCLKGEN, - .slowgen = BOARD_SERCOM2_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM2_PINMAP_PAD0, - .pad1 = BOARD_SERCOM2_PINMAP_PAD1, - .pad2 = BOARD_SERCOM2_PINMAP_PAD2, - .pad3 = BOARD_SERCOM2_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM2_MUXCONFIG, - .srcfreq = BOARD_SERCOM2_FREQUENCY, - .base = SAM_SERCOM2_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM2_GCLKGEN, + .slowgen = BOARD_SERCOM2_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM2_PINMAP_PAD0, + .pad1 = BOARD_SERCOM2_PINMAP_PAD1, + .pad2 = BOARD_SERCOM2_PINMAP_PAD2, + .pad3 = BOARD_SERCOM2_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM2_MUXCONFIG, + .srcfreq = BOARD_SERCOM2_FREQUENCY, + .base = SAM_SERCOM2_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM2_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM2_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM2_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM2_RX, #endif }; #endif @@ -390,24 +390,24 @@ static const struct spi_ops_s g_spi3ops = static struct sam_spidev_s g_spi3dev = { - .ops = &g_spi3ops, - .sercom = 3, + .ops = &g_spi3ops, + .sercom = 3, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM3, + .irq = SAM_IRQ_SERCOM3, #endif - .gclkgen = BOARD_SERCOM3_GCLKGEN, - .slowgen = BOARD_SERCOM3_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM3_PINMAP_PAD0, - .pad1 = BOARD_SERCOM3_PINMAP_PAD1, - .pad2 = BOARD_SERCOM3_PINMAP_PAD2, - .pad3 = BOARD_SERCOM3_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM3_MUXCONFIG, - .srcfreq = BOARD_SERCOM3_FREQUENCY, - .base = SAM_SERCOM3_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM3_GCLKGEN, + .slowgen = BOARD_SERCOM3_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM3_PINMAP_PAD0, + .pad1 = BOARD_SERCOM3_PINMAP_PAD1, + .pad2 = BOARD_SERCOM3_PINMAP_PAD2, + .pad3 = BOARD_SERCOM3_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM3_MUXCONFIG, + .srcfreq = BOARD_SERCOM3_FREQUENCY, + .base = SAM_SERCOM3_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM3_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM3_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM3_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM3_RX, #endif }; #endif @@ -440,24 +440,24 @@ static const struct spi_ops_s g_spi4ops = static struct sam_spidev_s g_spi4dev = { - .ops = &g_spi4ops, - .sercom = 4, + .ops = &g_spi4ops, + .sercom = 4, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM4, + .irq = SAM_IRQ_SERCOM4, #endif - .gclkgen = BOARD_SERCOM4_GCLKGEN, - .slowgen = BOARD_SERCOM4_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM4_PINMAP_PAD0, - .pad1 = BOARD_SERCOM4_PINMAP_PAD1, - .pad2 = BOARD_SERCOM4_PINMAP_PAD2, - .pad3 = BOARD_SERCOM4_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM4_MUXCONFIG, - .srcfreq = BOARD_SERCOM4_FREQUENCY, - .base = SAM_SERCOM4_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM4_GCLKGEN, + .slowgen = BOARD_SERCOM4_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM4_PINMAP_PAD0, + .pad1 = BOARD_SERCOM4_PINMAP_PAD1, + .pad2 = BOARD_SERCOM4_PINMAP_PAD2, + .pad3 = BOARD_SERCOM4_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM4_MUXCONFIG, + .srcfreq = BOARD_SERCOM4_FREQUENCY, + .base = SAM_SERCOM4_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM4_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM4_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM4_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM4_RX, #endif }; #endif @@ -490,24 +490,24 @@ static const struct spi_ops_s g_spi5ops = static struct sam_spidev_s g_spi5dev = { - .ops = &g_spi5ops, - .sercom = 5, + .ops = &g_spi5ops, + .sercom = 5, #if 0 /* Not used */ - .irq = SAM_IRQ_SERCOM5, + .irq = SAM_IRQ_SERCOM5, #endif - .gclkgen = BOARD_SERCOM5_GCLKGEN, - .slowgen = BOARD_SERCOM5_SLOW_GCLKGEN, - .pad0 = BOARD_SERCOM5_PINMAP_PAD0, - .pad1 = BOARD_SERCOM5_PINMAP_PAD1, - .pad2 = BOARD_SERCOM5_PINMAP_PAD2, - .pad3 = BOARD_SERCOM5_PINMAP_PAD3, - .muxconfig = BOARD_SERCOM5_MUXCONFIG, - .srcfreq = BOARD_SERCOM5_FREQUENCY, - .base = SAM_SERCOM5_BASE, - .spilock = SEM_INITIALIZER(1), + .gclkgen = BOARD_SERCOM5_GCLKGEN, + .slowgen = BOARD_SERCOM5_SLOW_GCLKGEN, + .pad0 = BOARD_SERCOM5_PINMAP_PAD0, + .pad1 = BOARD_SERCOM5_PINMAP_PAD1, + .pad2 = BOARD_SERCOM5_PINMAP_PAD2, + .pad3 = BOARD_SERCOM5_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM5_MUXCONFIG, + .srcfreq = BOARD_SERCOM5_FREQUENCY, + .base = SAM_SERCOM5_BASE, + .spilock = SEM_INITIALIZER(1), #ifdef CONFIG_SAMDL_SPI_DMA - .dma_tx_trig = DMAC_TRIGSRC_SERCOM5_TX, - .dma_rx_trig = DMAC_TRIGSRC_SERCOM5_RX, + .dma_tx_trig = DMAC_TRIGSRC_SERCOM5_TX, + .dma_rx_trig = DMAC_TRIGSRC_SERCOM5_RX, #endif }; #endif @@ -1103,26 +1103,41 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) return (uint16_t)rxbyte; } +/**************************************************************************** + * Name: spi_dma_callback + * + * Description: + * DMA completion callback + * + * Input Parameters: + * dma - Allocate DMA handle + * arg - User argument provided with callback + * result - The result of the DMA operation + * + * Returned Value: + * None + * + ****************************************************************************/ + #ifdef CONFIG_SAMDL_SPI_DMA static void spi_dma_callback(DMA_HANDLE dma, void *arg, int result) { struct sam_spidev_s *priv = (struct sam_spidev_s *)arg; - if(dma == priv->dma_rx) + if (dma == priv->dma_rx) { - /* Notify the blocked spi_exchange() call that the transaction * has completed by posting to the semaphore */ nxsem_post(&priv->dmasem); } - else if(dma == priv->dma_tx) + else if (dma == priv->dma_tx) { - if(result != OK) - { - spierr("DMA transmission failed\n"); - } + if (result != OK) + { + spierr("ERROR: DMA transmission failed: %d\n", result); + } } } #endif @@ -1156,11 +1171,11 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, { struct sam_spidev_s *priv = (struct sam_spidev_s *)dev; - spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); - #ifdef CONFIG_SAMDL_SPI_DMA - int ret; uint32_t regval; + int ret; + + spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); /* Disable SPI while we configure new DMA descriptors */ @@ -1171,8 +1186,10 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, /* Setup RX and TX DMA channels */ - sam_dmatxsetup(priv->dma_tx, priv->base + SAM_SPI_DATA_OFFSET, txbuffer, nwords); - sam_dmarxsetup(priv->dma_rx, priv->base + SAM_SPI_DATA_OFFSET, rxbuffer, nwords); + sam_dmatxsetup(priv->dma_tx, priv->base + SAM_SPI_DATA_OFFSET, + (uint32_t)txbuffer, nwords); + sam_dmarxsetup(priv->dma_rx, priv->base + SAM_SPI_DATA_OFFSET, + (uint32_t)rxbuffer, nwords); /* Start RX and TX DMA channels */ @@ -1200,6 +1217,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, uint8_t *prx8; uint16_t data; + spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); + /* Set up data receive and transmit pointers */ if (priv->nbits > 8) @@ -1416,10 +1435,17 @@ static void spi_pad_configure(struct sam_spidev_s *priv) } } +/**************************************************************************** + * Name: spi_dma_setup + * + * Description: + * Configure the SPI DMA operation. + * + ****************************************************************************/ + #ifdef CONFIG_SAMDL_SPI_DMA static void spi_dma_setup(struct sam_spidev_s *priv) { - /* Allocate a pair of DMA channels */ priv->dma_rx = sam_dmachannel(DMACH_FLAG_BEATSIZE_BYTE | @@ -1430,12 +1456,11 @@ static void spi_dma_setup(struct sam_spidev_s *priv) DMACH_FLAG_MEM_INCREMENT | DMACH_FLAG_PERIPH_TXTRIG(priv->dma_tx_trig)); - /* Initialize the samaphore used to notify when DMA is complete */ + /* Initialize the semaphore used to notify when DMA is complete */ nxsem_init(&priv->dmasem, 0, 0); nxsem_setprotocol(&priv->dmasem, SEM_PRIO_NONE); } - #endif /**************************************************************************** diff --git a/configs/flipnclick-pic32mz/README.txt b/configs/flipnclick-pic32mz/README.txt index 709430c39a..7321abd27c 100644 --- a/configs/flipnclick-pic32mz/README.txt +++ b/configs/flipnclick-pic32mz/README.txt @@ -82,8 +82,10 @@ Using the mikroProg =================== WARNINGS: + 1. Following there steps will most certainly overwrite the bootloader that was factory installed in FLASH! + 2. Due to the position and orientation of the mikroProg connector you may lose functionality: If you attach mikroProg to the red side of the board, you will not be able to use the Arduino Shield Connector @@ -91,8 +93,13 @@ Using the mikroProg side of the board, you will similarly lose access to mikroBUS connectors A and D. + Hindsight is 20/20 and in retrospect I would look for a right handler + header to priven the mikroProg connector from interfering with the + Arduino connection. + Hardware setup -------------- + You will need to add a five pin header to the mikroProg connector between the A and D mikroBUS sockets. @@ -107,6 +114,7 @@ Using the mikroProg Installing the Software ----------------------- + From the mikroProg website https://www.mikroe.com/mikroprog-pic-dspic-pic32 Download: diff --git a/configs/flipnclick-sam3x/README.txt b/configs/flipnclick-sam3x/README.txt index 1b8cadb610..393b83d00a 100644 --- a/configs/flipnclick-sam3x/README.txt +++ b/configs/flipnclick-sam3x/README.txt @@ -33,7 +33,7 @@ STATUS 2018-02-11: Added the nxlines configuration to test the custom HiletGo OLED on a Click proto board. This is the same logic from the Flip&Click PIC32MZ and the result is the same: No complaints from the software, but - nothing appears on the OLED. There is, most likely, an error in my custom + nothing appears on the OLED. There is, most likely, an error in my custom HiletGo Click. Damn! Buttons and LEDs @@ -633,4 +633,4 @@ Configuration sub-directories STATUS: 2018-02-11: No complaints from the software, but nothing appears on the - OLED. There is, most likely, an error in my custom HiletGo Click. Damn! + OLED. There is, most likely, an error in my custom HiletGo Click. Damn!