This commit is contained in:
Gregory Nutt 2016-04-27 00:19:22 -06:00
commit 48f66c15c1
13 changed files with 809 additions and 193 deletions

View File

@ -680,7 +680,10 @@
<td><br></td>
<td>
<p>
<li>Graphics: framebuffer drivers, graphic- and segment-LCD drivers.</li>
<li>
Graphics: framebuffer drivers, graphic- and segment-LCD drivers.
VNC server.
</li>
</p>
</td>
</tr>
@ -831,7 +834,8 @@
<td>
<p>
<li>Networking utilities (DHCP server and client, SMTP client, TELNET client, FTP server and client, TFTP client, HTTP server and client, PPPD, NTP client).
Inheritable TELNET sessions (as &quot;controlling terminal&quot;)</li>
Inheritable TELNET sessions (as &quot;controlling terminal&quot;).
VNC server.</li>
</p>
</td>
</tr>

View File

@ -833,14 +833,29 @@ Re-building
a file in one of the linked (i.e., copied) directories, re-build NuttX,
and then not see your changes when you run the program. That is because
build is still using the version of the file in the copied directory, not
your modified file! To work around this annoying behavior, do the
following when you re-build:
your modified file!
Older versions of NuttX did not support dependiencies in this
configuration. So a simple work around this annoying behavior in this
case was the following when you re-build:
make clean_context all
This 'make' command will remove of the copied directories, re-copy them,
then make NuttX.
However, more recent versions of NuttX do support dependencies for the
Cygwin build. As a result, the above command will cause everything to be
rebuilt (beause it removes and will cause recreating the
include/nuttx/config.h header file). A much less gracefully but still
effective command in this case is the following for the ARM configuration:
rm -rf arch/arm/src/chip arch/arm/src/board
This "kludge" simple removes the copied directories. These directories
will be re-created when you do a normal 'make' and your edits will then be
effective.
Build Targets and Options
-------------------------

View File

@ -69,6 +69,34 @@ config STM32L4_FLASH_1024KB
endchoice # Embedded FLASH size
comment "SRAM2 Options"
config STM32L4_SRAM2_HEAP
bool "SRAM2 is used for heap"
default n
select STM32L4_SRAM2_INIT
---help---
The STM32L4 SRAM2 region has special properties (power, protection, parity)
which may be used by the application for special purposes. But if these
special properties are not needed, it may be instead added to the heap for
use by malloc().
NOTE: you must also select an appropriate number of memory regions in the
'Memory Management' section.
config STM32L4_SRAM2_INIT
bool "SRAM2 is initialized to zero"
default n
---help---
The STM32L4 SRAM2 region has parity checking. However, when the system
powers on, the memory is in an unknown state, and reads from uninitialized
memory can trigger parity faults from the random data. This can be
avoided by first writing to all locations to force the parity into a valid
state.
However, if the SRAM2 is being used for it's battery-backed capability,
this may be undesireable (because it will destroy the contents). In that
case, the board should handle the initialization itself at the appropriate
time.
menu "STM32L4 Peripheral Support"
# These "hidden" settings determine is a peripheral option is available for the
@ -79,7 +107,7 @@ config STM32L4_HAVE_LTDC
default n
# These "hidden" settings are the OR of individual peripheral selections
# indicating that the general capabilitiy is required.
# indicating that the general capability is required.
config STM32L4_ADC
bool
@ -133,7 +161,6 @@ config STM32L4_DMA2
select STM32L4_DMA
select ARCH_DMA
config STM32L4_CRC
bool "CRC"
default n
@ -209,7 +236,119 @@ config STM32L4_QSPI_CSHT
---help---
The STM32L4 QSPI peripheral requires that it be specified the minimum number
of AHB cycles that Chip Select be held inactive between transactions.
choice
prompt "Transfer technique"
default STM32L4_QSPI_DMA
---help---
You can choose between using polling, interrupts, or DMA to transfer data
over the QSPI interface.
config STM32L4_QSPI_POLLING
bool "Polling"
---help---
Use conventional register I/O with status polling to transfer data.
config STM32L4_QSPI_INTERRUPTS
bool "Interrupts"
---help---
User interrupt driven I/O transfers.
config STM32L4_QSPI_DMA
bool "DMA"
depends on STM32L4_DMA
---help---
Use DMA to improve QSPI transfer performance.
endchoice
choice
prompt "DMA Channel"
default STM32L4_QSPI_DMA_CHAN_1_5
depends on STM32L4_DMA
---help---
You can choose between two DMA channels for use with QSPI:
either DMA1 channel 5, or DMA2 channel 7.
If you only see one choice here, it is probably because
you have not also enabled the associated DMA controller.
config STM32L4_QSPI_DMA_CHAN_1_5
bool "DMA1 Channel 5"
depends on STM32L4_DMA1
---help---
Use DMA1 channel 5 for QSPI.
config STM32L4_QSPI_DMA_CHAN_2_7
bool "DMA2 Channel 7"
depends on STM32L4_DMA2
---help---
Use DMA2 channel 7 for QSPI.
endchoice
choice
prompt "DMA Priority"
default STM32L4_QSPI_DMAPRIORITY_MEDIUM
depends on STM32L4_DMA
---help---
The DMA controller supports priority levels. You are probably fine
with the default of 'medium' except for special cases. In the event
of contention between to channels at the same priority, the lower
numbered channel has hardware priority over the higher numbered one.
config STM32L4_QSPI_DMAPRIORITY_VERYHIGH
bool "Very High priority"
depends on STM32L4_DMA
---help---
'Highest' priority.
config STM32L4_QSPI_DMAPRIORITY_HIGH
bool "High priority"
depends on STM32L4_DMA
---help---
'High' priority.
config STM32L4_QSPI_DMAPRIORITY_MEDIUM
bool "Medium priority"
depends on STM32L4_DMA
---help---
'Medium' priority.
config STM32L4_QSPI_DMAPRIORITY_LOW
bool "Low priority"
depends on STM32L4_DMA
---help---
'Low' priority.
endchoice
config STM32L4_QSPI_DMATHRESHOLD
int "QSPI DMA threshold"
default 4
depends on STM32L4_QSPI_DMA
---help---
When QSPI DMA is enabled, small DMA transfers will still be performed
by polling logic. This value is the threshold below which transfers
will still be performed by conventional register status polling.
config STM32L4_QSPI_DMADEBUG
bool "QSPI DMA transfer debug"
depends on STM32L4_QSPI_DMA && DEBUG && DEBUG_DMA
default n
---help---
Enable special debug instrumentation to analyze QSPI DMA data transfers.
This logic is as non-invasive as possible: It samples DMA
registers at key points in the data transfer and then dumps all of
the registers at the end of the transfer.
config STM32L4_QSPI_REGDEBUG
bool "QSPI Register level debug"
depends on DEBUG
default n
---help---
Output detailed register-level QSPI device debug information.
Requires also DEBUG.
endif
comment "APB1 Peripherals"

View File

@ -23,13 +23,13 @@ LSE : works, but TODO autotrim of MSI, etc
RCC : All registers defined, peripherals enabled, basic clock working
SYSCTL : All registers defined
USART : Working in normal mode (no DMA, to be tested, code is written)
DMA : Ported from STM32, code written, to be tested
DMA : works; at least tested with QSPI
SRAM2 : Should work with enough MM regions
FIREWALL : Code written, to be tested, requires support from ldscript
SPI : Code written, to be tested, including DMA
I2C : Registers defined
RTC : works
QSPI : TODO (port from stm32f7)
QSPI : works in polling, interrupt, DMA, and also memory-mapped modes
CAN : TODO
OTGFS : TODO
Timers : TODO

View File

@ -39,8 +39,7 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* These definitions apply to both the STM32 F1 and F3 families */
/* 12 Channels Total: 7 DMA1 Channels(1-7) and 5 DMA2 channels (1-5) */
/* 14 Channels Total: 7 DMA1 Channels(1-7) and 7 DMA2 channels (1-7) */
#define DMA1 0
#define DMA2 1
@ -158,6 +157,8 @@
#define STM32L4_DMA2_CCR3 (STM32L4_DMA2_BASE+STM32L4_DMA_CCR3_OFFSET)
#define STM32L4_DMA2_CCR4 (STM32L4_DMA2_BASE+STM32L4_DMA_CCR4_OFFSET)
#define STM32L4_DMA2_CCR5 (STM32L4_DMA2_BASE+STM32L4_DMA_CCR5_OFFSET)
#define STM32L4_DMA2_CCR6 (STM32L4_DMA2_BASE+STM32L4_DMA_CCR6_OFFSET)
#define STM32L4_DMA2_CCR7 (STM32L4_DMA2_BASE+STM32L4_DMA_CCR7_OFFSET)
#define STM32L4_DMA2_CNDTR(n) (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR_OFFSET(n))
#define STM32L4_DMA2_CNDTR1 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR1_OFFSET)
@ -165,6 +166,8 @@
#define STM32L4_DMA2_CNDTR3 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR3_OFFSET)
#define STM32L4_DMA2_CNDTR4 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR4_OFFSET)
#define STM32L4_DMA2_CNDTR5 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR5_OFFSET)
#define STM32L4_DMA2_CNDTR6 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR6_OFFSET)
#define STM32L4_DMA2_CNDTR7 (STM32L4_DMA2_BASE+STM32L4_DMA_CNDTR7_OFFSET)
#define STM32L4_DMA2_CPAR(n) (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR_OFFSET(n))
#define STM32L4_DMA2_CPAR1 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR1_OFFSET)
@ -172,6 +175,8 @@
#define STM32L4_DMA2_CPAR3 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR3_OFFSET)
#define STM32L4_DMA2_CPAR4 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR4_OFFSET)
#define STM32L4_DMA2_CPAR5 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR5_OFFSET)
#define STM32L4_DMA2_CPAR6 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR6_OFFSET)
#define STM32L4_DMA2_CPAR7 (STM32L4_DMA2_BASE+STM32L4_DMA_CPAR7_OFFSET)
#define STM32L4_DMA2_CMAR(n) (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR_OFFSET(n))
#define STM32L4_DMA2_CMAR1 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR1_OFFSET)
@ -179,6 +184,8 @@
#define STM32L4_DMA2_CMAR3 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR3_OFFSET)
#define STM32L4_DMA2_CMAR4 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR4_OFFSET)
#define STM32L4_DMA2_CMAR5 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR5_OFFSET)
#define STM32L4_DMA2_CMAR6 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR6_OFFSET)
#define STM32L4_DMA2_CMAR7 (STM32L4_DMA2_BASE+STM32L4_DMA_CMAR7_OFFSET)
/* Register Bitfield Definitions ****************************************************/

View File

@ -62,13 +62,13 @@
****************************************************************************/
/* Internal SRAM is available in all members of the STM32L4 family. The
* following definitions must be provided to specify the size and
* location of internal(system) SRAM:
* location of internal (system) SRAM1 and SRAM2:
*
* SRAM1_END 0x20018000
* SRAM2_START 0x10000000
* SRAM2_END 0x10008000
*
* In addition to internal SRAM, SRAM may also be available through the FSMC.
* In addition to internal SRAM, memory may also be available through the FSMC.
* In order to use FSMC SRAM, the following additional things need to be
* present in the NuttX configuration file:
*
@ -80,15 +80,14 @@
* CONFIG_HEAP2_SIZE : The size of the SRAM in the FSMC
* address space
* CONFIG_MM_REGIONS : Must be set to a large enough value to
* include the FSMC SRAM (as determined by
* the rules provided below)
* include the additional regions.
*/
#ifndef CONFIG_STM32L4_FSMC
# undef CONFIG_STM32L4_FSMC_SRAM
#endif
/* MSTM32L4x6xx have 128Kib in two banks, both accessible to DMA:
/* STM32L4x6xx have 128Kib in two banks, both accessible to DMA:
*
* 1) 96KiB of System SRAM beginning at address 0x2000:0000 - 0x2001:8000
* 2) 32KiB of System SRAM beginning at address 0x1000:0000 - 0x1000:8000
@ -105,55 +104,21 @@
#define SRAM2_START 0x10000000
#define SRAM2_END 0x10008000
/* Allocations according to the number of memory regions:
*
* 1 region available:
* - map it to SRAM1
* - warn that SRAM2 is not available for heap
* - if FMC is enabled, warn that it is not available for heap
*
* 2 regions available: map them to SRAM1 and SRAM2
* - map region 1 to SRAM1
* - map region 2 to SRAM2
* - if FMC is enabled, warn that it is not available for heap
*
* 3 or more regions
*
* - map them to SRAM1, SRAM2, FMC
*/
#if CONFIG_MM_REGIONS < 1
# warning heap is not usable
#elif CONFIG_MM_REGIONS < 2
# warning SRAM2 (32k) is NOT available for heap, only SRAM1 (96k) : not enough MM regions
# undef SRAM2_START
# undef SRAM2_END
# if defined(CONFIG_STM32L4_FSMC_SRAM)
# warning FMC SRAM is NOT available for heap : not enough MM regions (1)
# undef CONFIG_STM32L4_FSMC_SRAM
#if defined(STM32L4_SRAM2_HEAP) && defined(CONFIG_STM32L4_FSMC_SRAM_HEAP)
# if CONFIG_MM_REGIONS < 3
# error you need at least 3 memory manager regions to support SRAM2 and FSMC
# endif
#elif CONFIG_MM_REGIONS < 3
# if defined(CONFIG_STM32L4_FSMC_SRAM)
# warning FMC SRAM is NOT available for heap : not enough MM regions (2)
# undef CONFIG_STM32L4_FSMC_SRAM
# endif
#elif CONFIG_MM_REGIONS > 3
/*Everything can be mapped but some entries wont be used -> warn and correct*/
# warning "CONFIG_MM_REGIONS > 3 but I don't know what some of the region(s) are"
# undef CONFIG_MM_REGIONS
# define CONFIG_MM_REGIONS 3
#else
/*Everything can be mapped*/
#endif
#if defined(STM32L4_SRAM2_HEAP) || defined(CONFIG_STM32L4_FSMC_SRAM_HEAP)
# if CONFIG_MM_REGIONS < 2
# error you need at least 2 memory manager regions to support SRAM2 or FSMC
# endif
#endif
#if CONFIG_MM_REGIONS < 1
# warning you have no heap; malloc() will fail. are you sure?
#endif
/* If FSMC SRAM is going to be used as heap, then verify that the starting
* address and size of the external SRAM region has been provided in the
@ -338,6 +303,8 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size)
void up_addregion(void)
{
#ifdef CONFIG_STM32L4_SRAM2_HEAP
#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the SRAM2 heap */
@ -354,7 +321,9 @@ void up_addregion(void)
kumm_addregion((FAR void *)SRAM2_START, SRAM2_END-SRAM2_START);
#ifdef CONFIG_STM32L4_FSMC_SRAM
#endif
#ifdef CONFIG_STM32L4_FSMC_SRAM_HEAP
#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the FSMC SRAM user heap memory */

View File

@ -3,6 +3,8 @@
*
* Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Sebastien Lorquet <sebastien@lorquet.fr>
* dev@ziggurat29.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -57,13 +59,11 @@
* DMA callback function (see dma_callback_t).
*/
# define DMA_STATUS_FEIF 0 /* (Not available in F1) */
# define DMA_STATUS_DMEIF 0 /* (Not available in F1) */
# define DMA_STATUS_TEIF DMA_CHAN_TEIF_BIT /* Channel Transfer Error */
# define DMA_STATUS_HTIF DMA_CHAN_HTIF_BIT /* Channel Half Transfer */
# define DMA_STATUS_TCIF DMA_CHAN_TCIF_BIT /* Channel Transfer Complete */
#define DMA_STATUS_ERROR (DMA_STATUS_FEIF|DMA_STATUS_DMEIF|DMA_STATUS_TEIF)
#define DMA_STATUS_ERROR (DMA_STATUS_TEIF)
#define DMA_STATUS_SUCCESS (DMA_STATUS_TCIF|DMA_STATUS_HTIF)
/************************************************************************************
@ -71,7 +71,7 @@
************************************************************************************/
/* DMA_HANDLE provides an opaque are reference that can be used to represent a DMA
* channel (F1) or a DMA stream (F4).
* channel.
*/
typedef FAR void *DMA_HANDLE;
@ -81,7 +81,7 @@ typedef FAR void *DMA_HANDLE;
* completion of the DMA.
*
* Input Parameters:
* handle - Refers tot he DMA channel or stream
* handle - Refers tot he DMA channel
* status - A bit encoded value that provides the completion status. See the
* DMASTATUS_* definitions above.
* arg - A user-provided value that was provided when stm32l4_dmastart() was
@ -93,11 +93,12 @@ typedef void (*dma_callback_t)(DMA_HANDLE handle, uint8_t status, void *arg);
#ifdef CONFIG_DEBUG_DMA
struct stm32l4_dmaregs_s
{
uint32_t isr;
uint32_t ccr;
uint32_t cndtr;
uint32_t cpar;
uint32_t cmar;
uint32_t isr; /* Interrupt Status Register; each channel gets 4 bits */
uint32_t cselr; /* Channel Selection Register; chooses peripheral bound */
uint32_t ccr; /* Channel Configuration Register; determines functionality */
uint32_t cndtr; /* Channel Count Register; determines number of transfers */
uint32_t cpar; /* Channel Peripheral Address Register; determines start */
uint32_t cmar; /* Channel Memory Address Register; determines start */
};
#endif
@ -126,7 +127,7 @@ extern "C"
* Description:
* Allocate a DMA channel. This function gives the caller mutually
* exclusive access to the DMA channel specified by the 'chan' argument.
* DMA channels are shared on the STM32: Devices sharing the same DMA
* DMA channels are shared on the STM32L4: Devices sharing the same DMA
* channel cannot do DMA concurrently! See the DMACHAN_* definitions in
* stm32l4_dma.h.
*
@ -142,10 +143,8 @@ extern "C"
*
* Input parameter:
* chan - Identifies the stream/channel resource
* For the STM32 F1, this is simply the channel number as provided by
* the DMACHAN_* definitions in chip/stm32f10xxx_dma.h.
* For the STM32 F4, this is a bit encoded value as provided by the
* the DMAMAP_* definitions in chip/stm32f40xxx_dma.h
* This is a bit encoded value as provided by the DMACHAN_* definitions
* in chip/stm32l4x6xx_dma.h
*
* Returned Value:
* Provided that 'chan' is valid, this function ALWAYS returns a non-NULL,
@ -153,8 +152,8 @@ extern "C"
* assert if debug is enabled or do something ignorant otherwise).
*
* Assumptions:
* - The caller does not hold he DMA channel.
* - The caller can wait for the DMA channel to be freed if it is no
* - The caller does not hold the DMA channel.
* - The caller can wait for the DMA channel to be freed if it is not
* available.
*
****************************************************************************/

View File

@ -120,18 +120,12 @@
#define DMA_END_TRANSFER 4
#define DMA_NSAMPLES 5
#ifdef CONFIG_STM32L4_QSPI_DMA
# error QSPI DMA support not yet implemented
/* Can't have both interrupt-driven QSPI and DMA QSPI */
#if defined(STM32L4_QSPI_INTERRUPTS) && defined(CONFIG_STM32L4_QSPI_DMA)
# error "Cannot enable both interrupt mode and DMA mode for QSPI"
#endif
/* QSPI dma is not yet implemented */
#undef CONFIG_STM32L4_QSPI_DMA
/* QSPI Interrupt mode is implemented */
#define QSPI_USE_INTERRUPTS
/* Sanity check that board.h defines requisite QSPI pinmap options for */
#if (!defined(GPIO_QSPI_CS) || !defined(GPIO_QSPI_IO0) || !defined(GPIO_QSPI_IO1) || \
@ -141,9 +135,27 @@
#endif
#ifdef CONFIG_STM32L4_QSPI_DMA
# if !defined(DMACHAN_QUADSPI)
# if defined(CONFIG_STM32L4_QSPI_DMA_CHAN_1_5)
# define DMACHAN_QUADSPI DMACHAN_QUADSPI_1
# elif defined(CONFIG_STM32L4_QSPI_DMA_CHAN_2_7)
# define DMACHAN_QUADSPI DMACHAN_QUADSPI_2
# else
# error QSPI DMA channel must be specified via DMACHAN_QUADSPI in your board.h
# endif
# if defined(CONFIG_STM32L4_QSPI_DMAPRIORITY_LOW)
# define QSPI_DMA_PRIO DMA_CCR_PRILO
# elif defined(CONFIG_STM32L4_QSPI_DMAPRIORITY_MEDIUM)
# define QSPI_DMA_PRIO DMA_CCR_PRIMED
# elif defined(CONFIG_STM32L4_QSPI_DMAPRIORITY_HIGH)
# define QSPI_DMA_PRIO DMA_CCR_PRIHI
# elif defined(CONFIG_STM32L4_QSPI_DMAPRIORITY_VERYHIGH)
# define QSPI_DMA_PRIO DMA_CCR_PRIVERYHI
# else
# define QSPI_DMA_PRIO DMA_CCR_PRIMED
# endif
#endif
#ifndef BOARD_AHB_FREQUENCY
@ -154,6 +166,13 @@
# error you must specify a positive flash size via CONFIG_STM32L4_QSPI_FLASH_SIZE
#endif
/* DMA timeout. The value is not critical; we just don't want the system to
* hang in the event that a DMA does not finish.
*/
#define DMA_TIMEOUT_MS (800)
#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS)
/* Clocking *****************************************************************/
/* The QSPI bit rate clock is generated by dividing the peripheral clock by
* a value between 1 and 255
@ -184,7 +203,7 @@ struct stm32l4_qspidev_s
sem_t exclsem; /* Assures mutually exclusive access to QSPI */
bool memmap; /* TRUE: Controller is in memory mapped mode */
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
xcpt_t handler; /* Interrupt handler */
uint8_t irq; /* Interrupt number */
sem_t op_sem; /* Block until complete */
@ -192,7 +211,11 @@ struct stm32l4_qspidev_s
#endif
#ifdef CONFIG_STM32L4_QSPI_DMA
/* XXX III needs implementation */
bool candma; /* DMA is supported */
sem_t dmawait; /* Used to wait for DMA completion */
int result; /* DMA result */
DMA_HANDLE dmach; /* QSPI DMA handle */
WDOG_ID dmadog; /* Watchdog that handles DMA timeouts */
#endif
/* Debug stuff */
@ -238,7 +261,7 @@ struct qspi_xctnspec_s
uint8_t isddr; /* true if 'double data rate' */
uint8_t issioo; /* true if 'send instruction only once' mode */
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
uint8_t function; /* functional mode; to distinguish a read or write */
int8_t disposition; /* how it all turned out */
uint32_t idxnow; /* index into databuffer of current byte in transfer */
@ -277,11 +300,37 @@ static void qspi_dumpgpioconfig(const char *msg);
/* Interrupts */
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
static int qspi0_interrupt(int irq, void *context);
#endif
/* DMA support */
#ifdef CONFIG_STM32L4_QSPI_DMA
# if defined(CONFIG_QSPI_DMAPRIO)
# define QSPI_DMA_PRIO CONFIG_QSPI_DMAPRIO
# else
# define QSPI_DMA_PRIO DMA_CCR_PRIMED
# endif
# ifdef CONFIG_STM32L4_QSPI_DMADEBUG
# define qspi_dma_sample(s,i) stm32l4_dmasample((s)->dmach, &(s)->dmaregs[i])
static void qspi_dma_sampleinit(struct stm32l4_qspidev_s *priv);
static void qspi_dma_sampledone(struct stm32l4_qspidev_s *priv);
# else
# define qspi_dma_sample(s,i)
# define qspi_dma_sampleinit(s)
# define qspi_dma_sampledone(s)
# endif
# ifndef CONFIG_STM32L4_QSPI_DMATHRESHOLD
# define CONFIG_STM32L4_QSPI_DMATHRESHOLD 4
# endif
#endif
/* QSPI methods */
static int qspi_lock(struct qspi_dev_s *dev, bool lock);
@ -326,13 +375,13 @@ static struct stm32l4_qspidev_s g_qspi0dev =
.ops = &g_qspi0ops,
},
.base = STM32L4_QSPI_BASE,
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
.handler = qspi0_interrupt,
.irq = STM32L4_IRQ_QUADSPI,
#endif
.intf = 0,
#ifdef CONFIG_STM32L4_QSPI_DMA
/* XXX III needs implementation */
.candma = true,
#endif
};
@ -572,6 +621,93 @@ static void qspi_dumpgpioconfig(const char *msg)
}
#endif
#ifdef CONFIG_STM32L4_QSPI_DMADEBUG
/****************************************************************************
* Name: qspi_dma_sampleinit
*
* Description:
* Initialize sampling of DMA registers
*
* Input Parameters:
* priv - QSPI driver instance
*
* Returned Value:
* None
*
****************************************************************************/
static void qspi_dma_sampleinit(struct stm32l4_qspidev_s *priv)
{
/* Put contents of register samples into a known state */
memset(priv->dmaregs, 0xff, DMA_NSAMPLES * sizeof(struct stm32l4_dmaregs_s));
/* Then get the initial samples */
stm32l4_dmasample(priv->dmach, &priv->dmaregs[DMA_INITIAL]);
}
/****************************************************************************
* Name: qspi_dma_sampledone
*
* Description:
* Dump sampled DMA registers
*
* Input Parameters:
* priv - QSPI driver instance
*
* Returned Value:
* None
*
****************************************************************************/
static void qspi_dma_sampledone(struct stm32l4_qspidev_s *priv)
{
/* Sample the final registers */
stm32l4_dmasample(priv->dmach, &priv->dmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */
/* Initial register values */
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_INITIAL],
"Initial Registers");
/* Register values after DMA setup */
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_AFTER_SETUP],
"After DMA Setup");
/* Register values after DMA start */
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_AFTER_START],
"After DMA Start");
/* Register values at the time of the TX and RX DMA callbacks
* -OR- DMA timeout.
*
* If the DMA timed out, then there will not be any RX DMA
* callback samples. There is probably no TX DMA callback
* samples either, but we don't know for sure.
*/
if (priv->result == -ETIMEDOUT)
{
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_TIMEOUT],
"At DMA timeout");
}
else
{
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_CALLBACK],
"At DMA callback");
}
stm32l4_dmadump(priv->dmach, &priv->dmaregs[DMA_END_TRANSFER],
"At End-of-Transfer");
}
#endif
/****************************************************************************
* Name: qspi_setupxctnfromcmd
*
@ -687,7 +823,7 @@ static int qspi_setupxctnfromcmd(struct qspi_xctnspec_s *xctn,
xctn->isddr = 0;
}
#if defined(QSPI_USE_INTERRUPTS)
#if defined(STM32L4_QSPI_INTERRUPTS)
xctn->function = QSPICMD_ISWRITE(cmdinfo->flags) ? CCR_FMODE_INDWR : CCR_FMODE_INDRD;
xctn->disposition = - EIO;
xctn->idxnow = 0;
@ -816,7 +952,7 @@ static int qspi_setupxctnfrommem(struct qspi_xctnspec_s *xctn,
xctn->isddr = 0;
#if defined(QSPI_USE_INTERRUPTS)
#if defined(STM32L4_QSPI_INTERRUPTS)
xctn->function = QSPIMEM_ISWRITE(meminfo->flags) ? CCR_FMODE_INDWR : CCR_FMODE_INDRD;
xctn->disposition = - EIO;
xctn->idxnow = 0;
@ -938,7 +1074,7 @@ static void qspi_ccrconfig(struct stm32l4_qspidev_s *priv,
}
}
#if defined(QSPI_USE_INTERRUPTS)
#if defined(STM32L4_QSPI_INTERRUPTS)
/****************************************************************************
* Name: qspi0_interrupt
*
@ -1146,9 +1282,267 @@ static int qspi0_interrupt(int irq, void *context)
}
#elif defined(CONFIG_STM32L4_QSPI_DMA)
/* XXX III dma mode */
/****************************************************************************
* Name: qspi_dma_timeout
*
* Description:
* The watchdog timeout setup when a has expired without completion of a
* DMA.
*
* Input Parameters:
* argc - The number of arguments (should be 1)
* arg - The argument (state structure reference cast to uint32_t)
*
* Returned Value:
* None
*
* Assumptions:
* Always called from the interrupt level with interrupts disabled.
*
****************************************************************************/
#else
static void qspi_dma_timeout(int argc, uint32_t arg)
{
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)arg;
DEBUGASSERT(priv != NULL);
/* Sample DMA registers at the time of the timeout */
qspi_dma_sample(priv, DMA_CALLBACK);
/* Report timeout result, perhaps overwriting any failure reports from
* the TX callback.
*/
priv->result = -ETIMEDOUT;
/* Then wake up the waiting thread */
sem_post(&priv->dmawait);
}
/****************************************************************************
* Name: qspi_dma_callback
*
* Description:
* This callback function is invoked at the completion of the QSPI DMA.
*
* Input Parameters:
* handle - The DMA handler
* isr - source of the DMA interrupt
* arg - A pointer to the chip select structure
*
* Returned Value:
* None
*
****************************************************************************/
static void qspi_dma_callback(DMA_HANDLE handle, uint8_t isr, void *arg)
{
struct stm32l4_qspidev_s *priv = (struct stm32l4_qspidev_s *)arg;
DEBUGASSERT(priv != NULL);
/* Cancel the watchdog timeout */
(void)wd_cancel(priv->dmadog);
/* Sample DMA registers at the time of the callback */
qspi_dma_sample(priv, DMA_CALLBACK);
/* Report the result of the transfer only if the callback has not already
* reported an error.
*/
if (priv->result == -EBUSY)
{
/* Save the result of the transfer if no error was previously reported */
if ( isr & DMA_CHAN_TCIF_BIT )
{
priv->result = OK;
}
else if ( isr & DMA_CHAN_TEIF_BIT )
{
priv->result = -EIO;
}
else
{
priv->result = OK;
}
}
/* Then wake up the waiting thread */
sem_post(&priv->dmawait);
}
/****************************************************************************
* Name: qspi_regaddr
*
* Description:
* Return the address of an QSPI register
*
****************************************************************************/
static inline uintptr_t qspi_regaddr(struct stm32l4_qspidev_s *priv,
unsigned int offset)
{
return priv->base + offset;
}
/****************************************************************************
* Name: qspi_memory_dma
*
* Description:
* Perform one QSPI memory transfer using DMA
*
* Input Parameters:
* priv - Device-specific state data
* meminfo - Describes the memory transfer to be performed.
* xctn - Describes the transaction context.
*
* Returned Value:
* Zero (OK) on SUCCESS, a negated errno on value of failure
*
****************************************************************************/
static int qspi_memory_dma(struct stm32l4_qspidev_s *priv,
struct qspi_meminfo_s *meminfo,
struct qspi_xctnspec_s *xctn)
{
uint32_t dmaflags;
uint32_t regval;
int ret;
/* Initialize register sampling */
qspi_dma_sampleinit(priv);
/* Determine DMA flags and setup the DMA */
if (QSPIMEM_ISWRITE(meminfo->flags))
{
/* Setup the DMA (memory-to-peripheral) */
dmaflags = (QSPI_DMA_PRIO | DMA_CCR_MSIZE_8BITS | DMA_CCR_PSIZE_8BITS | DMA_CCR_MINC | DMA_CCR_DIR);
}
else
{
/* Setup the DMA (peripheral-to-memory) */
dmaflags = (QSPI_DMA_PRIO | DMA_CCR_MSIZE_8BITS | DMA_CCR_PSIZE_8BITS | DMA_CCR_MINC );
}
stm32l4_dmasetup(priv->dmach, qspi_regaddr(priv, STM32L4_QUADSPI_DR_OFFSET),
(uint32_t)meminfo->buffer, meminfo->buflen, dmaflags);
qspi_dma_sample(priv, DMA_AFTER_SETUP);
/* Enable the memory transfer */
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
regval |= QSPI_CR_DMAEN;
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
/* Set up the Communications Configuration Register as per command info */
qspi_ccrconfig(priv, xctn,
QSPIMEM_ISWRITE(meminfo->flags) ? CCR_FMODE_INDWR : CCR_FMODE_INDRD);
/* Start the DMA */
priv->result = -EBUSY;
stm32l4_dmastart(priv->dmach, qspi_dma_callback, priv, false);
qspi_dma_sample(priv, DMA_AFTER_START);
/* Wait for DMA completion. This is done in a loop because there may be
* false alarm semaphore counts that cause sem_wait() not fail to wait
* or to wake-up prematurely (for example due to the receipt of a signal).
* We know that the DMA has completed when the result is anything other
* that -EBUSY.
*/
do
{
/* Start (or re-start) the watchdog timeout */
ret = wd_start(priv->dmadog, DMA_TIMEOUT_TICKS,
(wdentry_t)qspi_dma_timeout, 1, (uint32_t)priv);
if (ret != OK)
{
qspidbg("ERROR: wd_start failed: %d\n", ret);
}
/* Wait for the DMA complete */
ret = sem_wait(&priv->dmawait);
/* Cancel the watchdog timeout */
(void)wd_cancel(priv->dmadog);
/* Check if we were awakened by an error of some kind */
if (ret < 0)
{
/* EINTR is not a failure. That simply means that the wait
* was awakened by a signal.
*/
int errorcode = errno;
if (errorcode != EINTR)
{
DEBUGPANIC();
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
regval &= ~QSPI_CR_DMAEN;
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
return -errorcode;
}
}
/* Note that we might be awakened before the wait is over due to
* residual counts on the semaphore. So, to handle, that case,
* we loop until something changes the DMA result to any value other
* than -EBUSY.
*/
}
while (priv->result == -EBUSY);
/* Wait for Transfer complete, and not busy */
qspi_waitstatusflags(priv, QSPI_SR_TCF,1);
qspi_waitstatusflags(priv, QSPI_SR_BUSY,0);
MEMORY_SYNC();
/* Dump the sampled DMA registers */
qspi_dma_sampledone(priv);
/* Make sure that the DMA is stopped (it will be stopped automatically
* on normal transfers, but not necessarily when the transfer terminates
* on an error condition).
*/
stm32l4_dmastop(priv->dmach);
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
regval &= ~QSPI_CR_DMAEN;
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
/* Complain if the DMA fails */
if (priv->result)
{
qspidbg("ERROR: DMA failed with result: %d\n", priv->result);
}
return priv->result;
}
#endif
#if !defined(STM32L4_QSPI_INTERRUPTS)
/****************************************************************************
* Name: qspi_receive_blocking
*
@ -1581,7 +1975,7 @@ static int qspi_command(struct qspi_dev_s *dev,
QSPI_FCR_CTEF | QSPI_FCR_CTCF | QSPI_FCR_CSMF | QSPI_FCR_CTOF,
STM32L4_QUADSPI_FCR);
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
/* interrupt mode will need access to the transaction context */
priv->xctn = &xctn;
@ -1665,9 +2059,9 @@ static int qspi_command(struct qspi_dev_s *dev,
ret = xctn.disposition;
#elif defined(CONFIG_STM32L4_QSPI_DMA)
/* XXX III dma mode (and 'autopolling'?) */
/* because command transfers are so small, we're not going to use
* DMA for them, only interrupts or polling
*/
#else
/* Polling mode */
@ -1762,7 +2156,7 @@ static int qspi_memory(struct qspi_dev_s *dev,
QSPI_FCR_CTEF | QSPI_FCR_CTCF | QSPI_FCR_CSMF | QSPI_FCR_CTOF,
STM32L4_QUADSPI_FCR);
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
/* interrupt mode will need access to the transaction context */
priv->xctn = &xctn;
@ -1824,8 +2218,46 @@ static int qspi_memory(struct qspi_dev_s *dev,
ret = xctn.disposition;
#elif defined(CONFIG_STM32L4_QSPI_DMA)
/* XXX III dma mode (and 'autopolling'?) */
/* Can we perform DMA? Should we perform DMA? */
if (priv->candma &&
meminfo->buflen > CONFIG_STM32L4_QSPI_DMATHRESHOLD &&
IS_ALIGNED((uintptr_t)meminfo->buffer) &&
IS_ALIGNED(meminfo->buflen))
{
ret = qspi_memory_dma(priv, meminfo, &xctn);
}
else
{
/* polling mode */
/* Set up the Communications Configuration Register as per command info */
qspi_ccrconfig(priv, &xctn,
QSPIMEM_ISWRITE(meminfo->flags) ? CCR_FMODE_INDWR : CCR_FMODE_INDRD);
/* Transfer data */
DEBUGASSERT(meminfo->buffer != NULL && meminfo->buflen > 0);
DEBUGASSERT(IS_ALIGNED(meminfo->buffer));
if (QSPIMEM_ISWRITE(meminfo->flags))
{
ret = qspi_transmit_blocking(priv, &xctn);
}
else
{
ret = qspi_receive_blocking(priv, &xctn);
}
/* Wait for Transfer complete, and not busy */
qspi_waitstatusflags(priv, QSPI_SR_TCF,1);
qspi_waitstatusflags(priv, QSPI_SR_BUSY,0);
MEMORY_SYNC();
}
#else
/* polling mode */
@ -1848,31 +2280,13 @@ static int qspi_memory(struct qspi_dev_s *dev,
ret = qspi_receive_blocking(priv, &xctn);
}
MEMORY_SYNC();
#if 0
#ifdef CONFIG_STM32L4_QSPI_DMA
/* Can we perform DMA? Should we perform DMA? */
if (priv->candma &&
meminfo->buflen > CONFIG_STM32L4_QSPI_DMATHRESHOLD &&
IS_ALIGNED((uintptr_t)meminfo->buffer) &&
IS_ALIGNED(meminfo->buflen))
{
return qspi_memory_dma(priv, meminfo);
}
else
#endif
{
return qspi_memory_nodma(priv, meminfo);
}
#endif
/* Wait for Transfer complete, and not busy */
qspi_waitstatusflags(priv, QSPI_SR_TCF,1);
qspi_waitstatusflags(priv, QSPI_SR_BUSY,0);
MEMORY_SYNC();
#endif
return ret;
@ -1949,7 +2363,7 @@ static int qspi_hw_initialize(struct stm32l4_qspidev_s *priv)
qspi_abort(priv);
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
regval = 0;
regval &= ~(QSPI_CR_EN);
qspi_putreg(priv, regval, STM32L4_QUADSPI_CR_OFFSET);
@ -2099,10 +2513,35 @@ struct qspi_dev_s *stm32l4_qspi_initialize(int intf)
sem_init(&priv->exclsem, 0, 1);
#ifdef CONFIG_STM32L4_QSPI_DMA
/* XXX III needs implementation */
/* Pre-allocate DMA channels. */
if (priv->candma)
{
priv->dmach = stm32l4_dmachannel(DMACHAN_QUADSPI);
if (!priv->dmach)
{
qspidbg("ERROR: Failed to allocate the DMA channel\n");
priv->candma = false;
}
}
/* Initialize the QSPI semaphore that is used to wake up the waiting
* thread when the DMA transfer completes.
*/
sem_init(&priv->dmawait, 0, 0);
/* Create a watchdog time to catch DMA timeouts */
priv->dmadog = wd_create();
if (priv->dmadog == NULL)
{
qspidbg("ERROR: Failed to create wdog\n");
goto errout_with_dmahandles;
}
#endif
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
/* Attach the interrupt handler */
ret = irq_attach(priv->irq, priv->handler);
@ -2133,7 +2572,7 @@ struct qspi_dev_s *stm32l4_qspi_initialize(int intf)
priv->initialized = true;
priv->memmap = false;
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
up_enable_irq(priv->irq);
#endif
}
@ -2141,13 +2580,22 @@ struct qspi_dev_s *stm32l4_qspi_initialize(int intf)
return &priv->qspi;
errout_with_irq:
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
irq_detach(priv->irq);
errout_with_dmadog:
#endif
#ifdef CONFIG_STM32L4_QSPI_DMA
/* XXX III needs implementation */
wd_delete(priv->dmadog);
errout_with_dmahandles:
sem_destroy(&priv->dmawait);
if (priv->dmach)
{
stm32l4_dmafree(priv->dmach);
priv->dmach = NULL;
}
#endif
sem_destroy(&priv->exclsem);
@ -2209,7 +2657,7 @@ void stm32l4_qspi_enter_memorymapped(struct qspi_dev_s* dev,
qspi_putreg(&g_qspi0dev, QSPI_FCR_CTOF, STM32L4_QUADSPI_FCR);
#ifdef QSPI_USE_INTERRUPTS
#ifdef STM32L4_QSPI_INTERRUPTS
/* Enable Timeout interrupt */
regval = qspi_getreg(priv, STM32L4_QUADSPI_CR_OFFSET);
@ -2227,7 +2675,10 @@ void stm32l4_qspi_enter_memorymapped(struct qspi_dev_s* dev,
/* create a transaction object */
qspi_setupxctnfrommem(&xctn, meminfo);
#ifdef STM32L4_QSPI_INTERRUPTS
priv->xctn = NULL;
#endif
/* set it into the ccr */

View File

@ -79,6 +79,8 @@
* 0x2001:7fff - End of internal SRAM and end of heap
*/
#define SRAM2_START 0x10000000
#define SRAM2_END 0x10008000
#define IDLE_STACK ((uintptr_t)&_ebss+CONFIG_IDLETHREAD_STACKSIZE-4)
#define HEAP_BASE ((uintptr_t)&_ebss+CONFIG_IDLETHREAD_STACKSIZE)
@ -287,6 +289,24 @@ void __start(void)
__asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : );
#endif
#ifdef CONFIG_STM32L4_SRAM2_INIT
/* The SRAM2 region is parity checked, but upon power up, it will be in
* a random state and probably invalid with respect to parity, potentially
* generating faults if accessed. If elected, we will write zeros to the
* memory, forcing the parity to be set to a valid state.
* NOTE: this is optional because this may be inappropriate, especially
* if the memory is being used for it's battery backed purpose. In that
* case, the first-time initialization needs to be performed by the board
* under application-specific circumstances. On the other hand, if we're
* using this memory for, say, additional heap space, then this is handy.
*/
for (dest = (uint32_t *)SRAM2_START; dest < (uint32_t *)SRAM2_END; )
{
*dest++ = 0;
}
#endif
/* Configure the UART so that we can get debug output as soon as possible */
stm32l4_clockconfig();

View File

@ -3,6 +3,8 @@
*
* Copyright (C) 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Sebastien Lorquet <sebastien@lorquet.fr>
* dev@ziggurat29.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -306,16 +308,17 @@ static int stm32l4_dmainterrupt(int irq, void *context)
isr = dmabase_getreg(dmach, STM32L4_DMA_ISR_OFFSET) & DMA_ISR_CHAN_MASK(dmach->chan);
/* Clear the interrupts we are handling */
dmabase_putreg(dmach, STM32L4_DMA_IFCR_OFFSET, isr);
/* Invoke the callback */
if (dmach->callback)
{
dmach->callback(dmach, isr >> DMA_ISR_CHAN_SHIFT(dmach->chan), dmach->arg);
}
/* Clear the interrupts we are handling */
dmabase_putreg(dmach, STM32L4_DMA_IFCR_OFFSET, isr);
return OK;
}
@ -387,9 +390,9 @@ void weak_function up_dmainitialize(void)
* version. Feel free to do that if that is what you need.
*
* Input parameter:
* chndx - Identifies the stream/channel resource. For the STM32 F1, this
* is simply the channel number as provided by the DMACHAN_* definitions
* in chip/stm32f10xxx_dma.h.
* chan - Identifies the stream/channel resource
* This is a bit encoded value as provided by the DMACHAN_* definitions
* in chip/stm32l4x6xx_dma.h
*
* Returned Value:
* Provided that 'chndx' is valid, this function ALWAYS returns a non-NULL,
@ -471,6 +474,9 @@ void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
struct stm32l4_dma_s *dmach = (struct stm32l4_dma_s *)handle;
uint32_t regval;
DEBUGASSERT(handle != NULL);
DEBUGASSERT(ntransfers<65536);
/* Then DMA_CNDTRx register can only be modified if the DMA channel is
* disabled.
*/
@ -514,7 +520,12 @@ void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
regval |= ccr;
dmachan_putreg(dmach, STM32L4_DMACHAN_CCR_OFFSET, regval);
#warning TODO define peripheral by using dmach->function
/* define peripheral indicated in dmach->function */
regval = dmabase_getreg(dmach, STM32L4_DMA_CSELR_OFFSET);
regval &= ~(0x0f << (dmach->chan << 2));
regval |= (dmach->function << (dmach->chan << 2));
dmabase_putreg(dmach, STM32L4_DMA_CSELR_OFFSET, regval);
}
/****************************************************************************
@ -641,7 +652,9 @@ bool stm32l4_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
* Transfers to/from memory performed by the DMA controller are
* required to be aligned to their size.
*
* See ST RM0090 rev4, section 9.3.11
* Datasheet 3.13 claims
* "Access to Flash, SRAM, APB and AHB peripherals as source
* and destination"
*
* Compute mend inline to avoid a possible non-constant integer
* multiply.
@ -682,13 +695,14 @@ bool stm32l4_dmacapable(uint32_t maddr, uint32_t count, uint32_t ccr)
switch (maddr & STM32L4_REGION_MASK)
{
#if defined(CONFIG_STM32L4_STM32F10XX)
case STM32L4_PERIPH_BASE:
case STM32L4_FSMC_BASE:
case STM32L4_FSMC_BANK1:
case STM32L4_FSMC_BANK2:
case STM32L4_FSMC_BANK3:
case STM32L4_FSMC_BANK4:
#endif
case STM32L4_SRAM_BASE:
case STM32L4_SRAM2_BASE:
case STM32L4_CODE_BASE:
/* All RAM and flash is supported */
@ -719,13 +733,14 @@ void stm32l4_dmasample(DMA_HANDLE handle, struct stm32l4_dmaregs_s *regs)
struct stm32l4_dma_s *dmach = (struct stm32l4_dma_s *)handle;
irqstate_t flags;
flags = irqsave();
flags = enter_critical_section();
regs->isr = dmabase_getreg(dmach, STM32L4_DMA_ISR_OFFSET);
regs->cselr = dmabase_getreg(dmach, STM32L4_DMA_CSELR_OFFSET);
regs->ccr = dmachan_getreg(dmach, STM32L4_DMACHAN_CCR_OFFSET);
regs->cndtr = dmachan_getreg(dmach, STM32L4_DMACHAN_CNDTR_OFFSET);
regs->cpar = dmachan_getreg(dmach, STM32L4_DMACHAN_CPAR_OFFSET);
regs->cmar = dmachan_getreg(dmach, STM32L4_DMACHAN_CMAR_OFFSET);
irqrestore(flags);
leave_critical_section(flags);
}
#endif
@ -748,7 +763,8 @@ void stm32l4_dmadump(DMA_HANDLE handle, const struct stm32l4_dmaregs_s *regs,
uint32_t dmabase = DMA_BASE(dmach->base);
dmadbg("DMA Registers: %s\n", msg);
dmadbg(" ISRC[%08x]: %08x\n", dmabase + STM32L4_DMA_ISR_OFFSET, regs->isr);
dmadbg(" ISR[%08x]: %08x\n", dmabase + STM32L4_DMA_ISR_OFFSET, regs->isr);
dmadbg(" CSELR[%08x]: %08x\n", dmabase + STM32L4_DMA_CSELR_OFFSET, regs->cselr);
dmadbg(" CCR[%08x]: %08x\n", dmach->base + STM32L4_DMACHAN_CCR_OFFSET, regs->ccr);
dmadbg(" CNDTR[%08x]: %08x\n", dmach->base + STM32L4_DMACHAN_CNDTR_OFFSET, regs->cndtr);
dmadbg(" CPAR[%08x]: %08x\n", dmach->base + STM32L4_DMACHAN_CPAR_OFFSET, regs->cpar);

View File

@ -144,16 +144,6 @@
#define GPIO_QSPI_IO3 (GPIO_QSPI_BK1_IO3_2 | GPIO_FLOAT | GPIO_PUSHPULL | GPIO_SPEED_100MHz)
#define GPIO_QSPI_SCK (GPIO_QSPI_CLK_2 | GPIO_FLOAT | GPIO_PUSHPULL | GPIO_SPEED_100MHz)
#if 0
/* XXX hmm, elsewhere */
#define QSPI_USE_INTERRUPTS 1
/* XXX hmm, better? (2^(23+1)); this is the value that goes into FSIZE */
#define QSPI_FLASH_SIZE 23
#endif
/* SPI */
/* XXX is SPI1 used on Disco? */

View File

@ -59,6 +59,7 @@ CONFIG_DEBUG_VERBOSE=y
#
# OS Function Debug Options
#
# CONFIG_DEBUG_DMA is not set
# CONFIG_DEBUG_HEAP is not set
# CONFIG_DEBUG_IRQ is not set
@ -176,6 +177,7 @@ CONFIG_ARMV7M_HAVE_STACKCHECK=y
# CONFIG_ARMV7M_ITMSYSLOG is not set
# CONFIG_SERIAL_TERMIOS is not set
# CONFIG_USART2_RS485 is not set
# CONFIG_USART2_RXDMA is not set
# CONFIG_SERIAL_DISABLE_REORDERING is not set
#
@ -197,7 +199,7 @@ CONFIG_STM32L4_FLASH_1024KB=y
# CONFIG_STM32L4_ADC is not set
# CONFIG_STM32L4_CAN is not set
# CONFIG_STM32L4_DAC is not set
# CONFIG_STM32L4_DMA is not set
CONFIG_STM32L4_DMA=y
# CONFIG_STM32L4_I2C is not set
# CONFIG_STM32L4_SAI is not set
# CONFIG_STM32L4_SPI is not set
@ -207,8 +209,8 @@ CONFIG_STM32L4_USART=y
#
# AHB1 Peripherals
#
# CONFIG_STM32L4_DMA1 is not set
# CONFIG_STM32L4_DMA2 is not set
CONFIG_STM32L4_DMA1=y
CONFIG_STM32L4_DMA2=y
# CONFIG_STM32L4_CRC is not set
# CONFIG_STM32L4_TSC is not set
@ -230,6 +232,17 @@ CONFIG_STM32L4_QSPI=y
CONFIG_STM32L4_QSPI_FLASH_SIZE=16777216
CONFIG_STM32L4_QSPI_FIFO_THESHOLD=4
CONFIG_STM32L4_QSPI_CSHT=1
# CONFIG_STM32L4_QSPI_POLLING is not set
# CONFIG_STM32L4_QSPI_INTERRUPTS is not set
CONFIG_STM32L4_QSPI_DMA=y
CONFIG_STM32L4_QSPI_DMA_CHAN_1_5=y
# CONFIG_STM32L4_QSPI_DMA_CHAN_2_7 is not set
# CONFIG_STM32L4_QSPI_DMAPRIORITY_VERYHIGH is not set
# CONFIG_STM32L4_QSPI_DMAPRIORITY_HIGH is not set
CONFIG_STM32L4_QSPI_DMAPRIORITY_MEDIUM=y
# CONFIG_STM32L4_QSPI_DMAPRIORITY_LOW is not set
CONFIG_STM32L4_QSPI_DMATHRESHOLD=4
# CONFIG_STM32L4_QSPI_REGDEBUG is not set
#
# APB1 Peripherals
@ -302,7 +315,7 @@ CONFIG_STM32L4_SAI1PLL=y
#
# CONFIG_ARCH_NOINTC is not set
# CONFIG_ARCH_VECNOTIRQ is not set
# CONFIG_ARCH_DMA is not set
CONFIG_ARCH_DMA=y
CONFIG_ARCH_HAVE_IRQPRIO=y
# CONFIG_ARCH_L2CACHE is not set
# CONFIG_ARCH_HAVE_COHERENT_DCACHE is not set
@ -384,7 +397,7 @@ CONFIG_LIB_BOARDCTL=y
# CONFIG_BOARDCTL_ADCTEST is not set
# CONFIG_BOARDCTL_PWMTEST is not set
# CONFIG_BOARDCTL_GRAPHICS is not set
# CONFIG_BOARDCTL_IOCTL is not set
CONFIG_BOARDCTL_IOCTL=y
#
# RTOS Features
@ -646,12 +659,7 @@ CONFIG_USART2_2STOP=0
#
# System Logging
#
CONFIG_RAMLOG=y
CONFIG_RAMLOG_SYSLOG=y
# CONFIG_RAMLOG_CONSOLE is not set
CONFIG_RAMLOG_BUFSIZE=8192
# CONFIG_RAMLOG_CRLF is not set
CONFIG_RAMLOG_NONBLOCKING=y
# CONFIG_RAMLOG is not set
# CONFIG_SYSLOG_CONSOLE is not set
#
@ -708,9 +716,8 @@ CONFIG_FS_PROCFS_REGISTER=y
#
# System Logging
#
CONFIG_SYSLOG=y
# CONFIG_SYSLOG is not set
# CONFIG_SYSLOG_TIMESTAMP is not set
# CONFIG_SYSLOG_CHAR is not set
#
# Graphics Support
@ -838,14 +845,7 @@ CONFIG_EXAMPLES_BUTTONS_NAME7="Button 7"
# CONFIG_EXAMPLES_CXXTEST is not set
# CONFIG_EXAMPLES_DHCPD is not set
# CONFIG_EXAMPLES_ELF is not set
CONFIG_EXAMPLES_FSTEST=y
CONFIG_EXAMPLES_FSTEST_MAXNAME=32
CONFIG_EXAMPLES_FSTEST_MAXFILE=8192
CONFIG_EXAMPLES_FSTEST_MAXIO=347
CONFIG_EXAMPLES_FSTEST_MAXOPEN=512
CONFIG_EXAMPLES_FSTEST_MOUNTPT="/mnt/n25qxxx"
CONFIG_EXAMPLES_FSTEST_NLOOPS=1
CONFIG_EXAMPLES_FSTEST_VERBOSE=y
# CONFIG_EXAMPLES_FSTEST is not set
# CONFIG_EXAMPLES_FTPC is not set
# CONFIG_EXAMPLES_FTPD is not set
# CONFIG_EXAMPLES_HELLO is not set
@ -871,20 +871,12 @@ CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y
# CONFIG_EXAMPLES_NXIMAGE is not set
# CONFIG_EXAMPLES_NXLINES is not set
# CONFIG_EXAMPLES_NXTEXT is not set
CONFIG_EXAMPLES_OSTEST=y
CONFIG_EXAMPLES_OSTEST_LOOPS=1
CONFIG_EXAMPLES_OSTEST_STACKSIZE=8192
CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS=8
CONFIG_EXAMPLES_OSTEST_RR_RANGE=10000
CONFIG_EXAMPLES_OSTEST_RR_RUNS=10
CONFIG_EXAMPLES_OSTEST_WAITRESULT=y
# CONFIG_EXAMPLES_OSTEST is not set
# CONFIG_EXAMPLES_PCA9635 is not set
# CONFIG_EXAMPLES_PIPE is not set
# CONFIG_EXAMPLES_PPPD is not set
# CONFIG_EXAMPLES_POSIXSPAWN is not set
CONFIG_EXAMPLES_RANDOM=y
CONFIG_EXAMPLES_MAXSAMPLES=64
CONFIG_EXAMPLES_NSAMPLES=8
# CONFIG_EXAMPLES_RANDOM is not set
# CONFIG_EXAMPLES_RGBLED is not set
# CONFIG_EXAMPLES_RGMP is not set
# CONFIG_EXAMPLES_SENDMAIL is not set

View File

@ -45,6 +45,8 @@
#include <syslog.h>
#include <errno.h>
#include <debug.h>
#include <string.h>
#include <stdlib.h>
#include <nuttx/arch.h>
#include <nuttx/board.h>
@ -57,6 +59,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ramdisk.h>
#include <nuttx/fs/nxffs.h>
#include <nuttx/fs/mkfatfs.h>
#include <nuttx/binfmt/elf.h>
#include <nuttx/i2c/i2c_master.h>
@ -193,6 +196,7 @@ int board_app_initialize(void)
#ifdef HAVE_N25QXXX_SMARTFS
/* Configure the device with no partition support */
SYSLOG("doing smart_initialize()\n");
ret = smart_initialize(N25QXXX_SMART_MINOR, mtd, NULL);
if (ret != OK)
{
@ -202,6 +206,7 @@ int board_app_initialize(void)
#elif defined(HAVE_N25QXXX_NXFFS)
/* Initialize to provide NXFFS on the N25QXXX MTD interface */
SYSLOG("doing nxffs_initialize()\n");
ret = nxffs_initialize(mtd);
if (ret < 0)
{
@ -237,9 +242,9 @@ int board_app_initialize(void)
/* NOTE: for this to work, you will need to make sure that
* CONFIG_FS_WRITABLE is set in the config. It's not a user-
* visible setting, but you can make it set by selecting an
* arbitrary writeable file system (you don't have to actually
* arbitrary writable file system (you don't have to actually
* use it, just select it so that the block device created via
* ftl_initialize() will be writeable). Personally, I chose FAT,
* ftl_initialize() will be writable). Personally, I chose FAT,
* because SMARTFS and NXFFS will cause the other code branches
* above to become active.
*/
@ -257,3 +262,12 @@ int board_app_initialize(void)
return OK;
}
#endif /* CONFIG_LIB_BOARDCTL */
#ifdef CONFIG_BOARDCTL_IOCTL
int board_ioctl(unsigned int cmd, uintptr_t arg)
{
return OK;
}
#endif