Merged nuttx/nuttx into master

This commit is contained in:
ziggurat29
2016-05-29 15:19:00 -05:00
55 changed files with 2175 additions and 493 deletions
+66 -63
View File
@@ -1,20 +1,20 @@
NuttX TODO List (Last updated March 31, 2016)
NuttX TODO List (Last updated May 28, 2016)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
standards, things that could be improved, and ideas for enhancements. This
TODO list does not include issues associated with individual boar ports. See
altheso individual README.txt files in the configs/ sub-directories for
issues reated to each board port.
also the individual README.txt files in the configs/ sub-directories for
issues related to each board port.
nuttx/
nuttx/:
(13) Task/Scheduler (sched/)
(1) Memory Management (mm/)
(3) Signals (sched/signal, arch/)
(2) pthreads (sched/pthread)
(0) Message Queues (sched/mqueue)
(8) Kernel/Protected Build
(9) Kernel/Protected Build
(3) C++ Support
(6) Binary loaders (binfmt/)
(12) Network (net/, drivers/net)
@@ -23,16 +23,16 @@ nuttx/
(11) Libraries (libc/, libm/)
(11) File system/Generic drivers (fs/, drivers/)
(8) Graphics subsystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Build system / Toolchains
(4) Linux/Cywgin simulation (arch/sim)
(3) Linux/Cywgin simulation (arch/sim)
(4) ARM (arch/arm/)
apps/
apps/ and other Add-Ons:
(3) Network Utilities (apps/netutils/)
(2) NuttShell (NSH) (apps/nshlib)
(1) System libraries apps/system (apps/system)
(1) Pascal add-on (pcode/)
(4) Other Applications & Tests (apps/examples/)
o Task/Scheduler (sched/)
@@ -70,7 +70,7 @@ o Task/Scheduler (sched/)
Title: GET_ENVIRON_PTR()
Description: get_environ_ptr() (sched/sched_getenvironptr.c) is not implemented.
The representation of the environment strings selected for
NutX is not compatible with the operation. Some significant
NuttX is not compatible with the operation. Some significant
re-design would be required to implement this function and that
effort is thought to be not worth the result.
Status: Open. No change is planned.
@@ -81,7 +81,7 @@ o Task/Scheduler (sched/)
Status: Open
Priority: Low -- There is no plan to implement this.
Title: INCOMPATIBILITES WITH execv() AND execl()
Title: INCOMPATIBILITIES WITH execv() AND execl()
Description: Simplified 'execl()' and 'execv()' functions are provided by
NuttX. NuttX does not support processes and hence the concept
of overlaying a tasks process image with a new process image
@@ -175,7 +175,7 @@ o Task/Scheduler (sched/)
Yahoo! Groups message 7726: "I think that the system
should be required to handle pthread_cancel safely in
all cases. In the NuttX model, a task is like a Unix
process and a pthread is like a Unix thread. Cancelling
process and a pthread is like a Unix thread. Canceling
threads should always be safe (or at least as unsafe) as
under Unix because the model is complete for pthreads...
@@ -188,7 +188,7 @@ o Task/Scheduler (sched/)
"The patch I just incorporated is also insufficient. It
works only if the serial driver is shut down when the
thread is cancelled. But what if there are other open
thread is canceled. But what if there are other open
references to the driver? Then the driver will not be
shut down, the semaphores will not be re-initialized, and
the semaphore counts will still be off by one.
@@ -202,7 +202,7 @@ o Task/Scheduler (sched/)
hooks so that given a semaphore it can traverse all
holders. What is needed would be logic so that given
a task, you can traverse all semaphores held by the task,
releasing each semaphore cound held by the exiting task.
releasing each semaphore count held by the exiting task.
Nothing like this exists now so that solution is not
imminent.
@@ -228,16 +228,15 @@ o Task/Scheduler (sched/)
hidden behind simple accessor functions and so the internal
data structures can be changed if need with very little impact.
Explicity refereence to the list strucutre are hidden behnid
Explicitly reference to the list structure are hidden behind
the macro this_task().
Status: Open
Priority: Low. Things are just the way that we want them for the way
that NuttX is used today.
o Memory Managment (mm/)
^^^^^^^^^^^^^^^^^^^^^^
o Memory Management (mm/)
^^^^^^^^^^^^^^^^^^^^^^^
Title: FREE MEMORY ON TASK EXIT
Description: Add an option to free all memory allocated by a task when the
@@ -390,7 +389,7 @@ o pthreads (sched/pthreads)
Priority: Low -- about zero, probably not that useful. Priority inheritance is
already supported and is a much better solution. And it turns out
that priority protection is just about as complex as priority inheritance.
Exerpted from my post in a Linked-In discussion:
Excerpted from my post in a Linked-In discussion:
"I started to implement this HLS/"PCP" semaphore in an RTOS that I
work with (http://www.nuttx.org) and I discovered after doing the
@@ -589,8 +588,21 @@ o Kernel/Protected Build
interrupt level callbacks into applications. This, of course,
will never work in anything but a non-secure, flat build.
Status: Open
Priority: Medium. The driver is only usable with all of its features in a FLAT build.
Priority: Medium. The driver is only usable with all of its features
in a FLAT build.
Title: USER MODE TASKS CAN MODIFY PRIVILEGED TASKS
Description: Certain interfaces, such as sched_setparam(),
sched_setscheduler(), etc. can be used by user mode tasks to
modify the behavior of priviledged kernel threads.
task_delete() could even be used to kill a kernel thread.
For a truly secure system. Privileges need to be checked in
every interface that permits one thread to modify the
properties of another thread.
Status: Open
Priority: Low for most embedded systems but would be a critical need if
NuttX were used in a secure system.
o C++ Support
^^^^^^^^^^^
@@ -784,7 +796,7 @@ o Binary loaders (binfmt/)
to get fixed as needed for Windows native tool builds.
Title: TOOLCHAIN COMPATIBILITY PROBLEM
Descripton: The older 4.3.3 compiler generates GOTOFF relocations to the constant
Description: The older 4.3.3 compiler generates GOTOFF relocations to the constant
strings, like:
.L3:
@@ -794,7 +806,7 @@ o Binary loaders (binfmt/)
.word .LC3(GOTOFF)
.word .LC4(GOTOFF)
Where .LC0, LC1, LC2, LC3, and .LC4 are the labels correponding to strings in
Where .LC0, LC1, LC2, LC3, and .LC4 are the labels corresponding to strings in
the .rodata.str1.1 section. One consequence of this is that .rodata must reside
in D-Space since it will addressed relative to the GOT (see the section entitled
"Read-Only Data in RAM" at
@@ -880,7 +892,7 @@ o Network (net/, drivers/net)
RFC3678 (IGMPv3) suggests ioctl() commands to do this (SIOCSIPMSFILTER) but
also status that those APIs are historic. NuttX implements these ioctl
commands, but is non-standard because: (1) It does not support IGMPv3, and
(2) it looks up drivers by their device name (eg., "eth0") vs IP address.
(2) it looks up drivers by their device name (e.g., "eth0") vs IP address.
Linux uses setsockopt() to control multicast group membership using the
IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP options. It also looks up drivers
@@ -896,7 +908,7 @@ o Network (net/, drivers/net)
that connection may time out. How should this be handled? Should the
connection be removed from the backlog if it is times out or is closed?
Or should it remain in the backlog with a status indication so that accept()
can fail when it encounteres the invalid connection?
can fail when it encounters the invalid connection?
Status: Open
Priority: Medium. Important on slow applications that will not accept
connections promptly.
@@ -975,7 +987,7 @@ o Network (net/, drivers/net)
it is no longer needed. Perhaps there should be a delayed
call to unlink() (using a watchdog or the work queue). If
the driver is re-opened, the delayed unlink could be
cancelled? Needs more thought.
canceled? Needs more thought.
NOTE: This is not an issue for Unix domain streams sockets:
The end-of-life of the FIFO is well determined when sockets
are disconnected and support for that case is fully implemented.
@@ -1020,7 +1032,7 @@ o USB (drivers/usbdev, drivers/usbhost)
that involves delays. This needs to be redesigned to eliminate these
delays. See logic conditioned on CONFIG_USBMSC_RACEWAR.
If queuing of stall requests is supported by DCD then this workaround
If queuing of stall requests is supported by the DCD then this workaround
is not required. In this case, (1) the stall is not sent until all
write requests preceding the stall request are sent, (2) the stall is
sent, and then after the stall is cleared, (3) all write requests
@@ -1135,7 +1147,7 @@ o USB (drivers/usbdev, drivers/usbhost)
Priority: Medium-Low
Title: USB CDC/ACM HOST CLASS DRIVER
Desciption: A CDC/ACM host class driver has been added. This has been
Description: A CDC/ACM host class driver has been added. This has been
testing by running the USB CDC/ACM host on an Olimex
LPC1766STK and using the configs/stm3210e-eval/usbserial
configuration (using the CDC/ACM device side driver). There
@@ -1374,7 +1386,7 @@ o File system / Generic drivers (fs/, drivers/)
Priority: Medium
Title: UNIFIED DESCRIPTOR REPRESENTATION
Descripton: There are two separate ranges of descriptors for file and
Description: There are two separate ranges of descriptors for file and
socket descriptors: if a descriptor is in one range then it is
recognized as a file descriptor; if it is in another range
then it is recognized as a socket descriptor. These separate
@@ -1410,7 +1422,7 @@ o File system / Generic drivers (fs/, drivers/)
Status: Open
Priority: Low
Title: FAT LONG FILENAME COMPATIBILTY
Title: FAT LONG FILENAME COMPATIBILITY
Description: Recently there have been reports that file with long file
names created by NuttX don't have long file names when viewed
on Windows. The long file name support has been around for a
@@ -1423,7 +1435,7 @@ o File system / Generic drivers (fs/, drivers/)
Description: I have seen cases where (1) long file names are enabled,
but (2) a short file name is created like:
nsh> echo "This is another thest" >/mnt/sdcard/another.txt
nsh> echo "This is another test" >/mnt/sdcard/another.txt
But then on subsequent 'ls' operations, the file does not appear:
@@ -1472,7 +1484,7 @@ o File system / Generic drivers (fs/, drivers/)
4) When comparing the checksum in the long file name
entry with the checksum of the short file name, the
checksum fails and the entire directlry sequence is
checksum fails and the entire directory sequence is
ignored by readder() logic. This the file does not
appear in the 'ls'.
@@ -1539,7 +1551,7 @@ o Graphics subsystem (graphics/)
Priority: Low, the need has not yet arisen.
Title: PER-WINDOW FRAMEBUFFERS
Description: One of the most awkard things to handle in the NX windowing
Description: One of the most awkward things to handle in the NX windowing
system is the re-draw callback. This is difficult because it
requires ad hoc, custom logic to be able to do the redrawing
in most cases.
@@ -1567,26 +1579,6 @@ o Graphics subsystem (graphics/)
Priority: Low, not a serious issue but worth noting. There is no plan
to change this behavior.
o Pascal Add-On (pcode/)
^^^^^^^^^^^^^^^^^^^^^^
Title: P-CODES IN MEMORY UNTESTED
Description: Need APIs to verify execution of P-Code from memory buffer.
Status: Open
Priority: Low
Title: SMALLER LOADER AND OBJECT FORMAT
Description: Loader and object format may be too large for some small
memory systems. Consider ways to reduce memory footprint.
Status: Open
Priority: Medium
Title: PDBG
Description: Move the the pascal p-code debugger into the NuttX apps/ tree
where it can be used from the NSH command line.
Status: Open
Priority: Low
o Build system
^^^^^^^^^^^^
@@ -1609,15 +1601,6 @@ o Other drivers (drivers/)
o Linux/Cywgin simulation (arch/sim)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: SIMULATOR NETWORKING SUPPORT
Description: I never did get networking to work on the sim Linux target. On Linux,
it tries to use the tap device (/dev/net/tun) to emulate an Ethernet
NIC, but I never got it correctly integrated with the NuttX networking.
NOTE: On Cygwin, the build uses the Cygwin WPCAP library and is, at
least, partially functional (it has never been rigorously tested).
Status: Open
Priority: Low (unless you want to test networking features on the simulation).
Title: SIMULATOR HAS NO INTERRUPTS (NON-PREMPTIBLE)
Description: The current simulator implementation is has no interrupts and, hence,
is non-preemptible. Also, without simulated interrupt, there can
@@ -1765,7 +1748,7 @@ o ARM (arch/arm/)
But this has not been proven to be a solution.
UPDATE: Other ARM architectures have a similer issue.
UPDATE: Other ARM architectures have a similar issue.
Status: Open
Priority: Low. The conditions of continuous interrupts is really the problem.
@@ -1823,7 +1806,7 @@ o NuttShell (NSH) (apps/nshlib)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: IFCONFIG AND MULTIPLE NETWORK INTERFACES
Descripton: The ifconfig command will not behave correctly if an interface
Description: The ifconfig command will not behave correctly if an interface
is provided and there are multiple interfaces. It should only
show status for the single interface on the command line; it will
still show status for all interfaces.
@@ -1848,6 +1831,26 @@ o System libraries apps/system (apps/system)
Priority: Low (unless you are using mixed C-buffered I/O with readline and
fgetc, for example).
o Pascal Add-On (pcode/)
^^^^^^^^^^^^^^^^^^^^^^
Title: P-CODES IN MEMORY UNTESTED
Description: Need APIs to verify execution of P-Code from memory buffer.
Status: Open
Priority: Low
Title: SMALLER LOADER AND OBJECT FORMAT
Description: Loader and object format may be too large for some small
memory systems. Consider ways to reduce memory footprint.
Status: Open
Priority: Medium
Title: PDBG
Description: Move the the pascal p-code debugger into the NuttX apps/ tree
where it can be used from the NSH command line.
Status: Open
Priority: Low
o Other Applications & Tests (apps/examples/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2 -2
View File
@@ -1568,7 +1568,7 @@
# define STM32_NGTIMNDMA 3 /* 16-bit general timers TIM9-11 without DMA */
# define STM32_NBTIM 0 /* No basic timers */
# define STM32_NDMA 2 /* DMA1-2 with 8 streams each*/
# define STM32_NSPI 4 /* SPI1-4 */
# define STM32_NSPI 5 /* SPI1-5 */
# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
# define STM32_NUSART 6 /* Actually only 3: USART1, 2 and 6 */
# define STM32_NI2C 3 /* I2C1-3 */
@@ -1606,7 +1606,7 @@
# define STM32_NGTIMNDMA 3 /* 16-bit general timers TIM9-11 without DMA */
# define STM32_NBTIM 0 /* No basic timers */
# define STM32_NDMA 2 /* DMA1-2 with 8 streams each*/
# define STM32_NSPI 4 /* SPI1-4 */
# define STM32_NSPI 5 /* SPI1-5 */
# define STM32_NI2S 2 /* I2S1-2 (multiplexed with SPI2-3) */
# define STM32_NUSART 6 /* Actually only 3: USART1, 2 and 6 */
# define STM32_NI2C 3 /* I2C1-3 */
+45 -12
View File
@@ -2,7 +2,9 @@
* arch/arm/src/efm32/efm32_adc.c
*
* Copyright (C) 2014 Bouteville Pierre-Noel. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Authors: Bouteville Pierre-Noel <pnb990@gmail.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -63,9 +65,9 @@
#include "efm32.h"
#include "efm32_adc.h"
/* ADC "upper half" support must be enabled */
/* ADC "lower half" support must be enabled */
#ifdef CONFIG_ADC
#ifdef CONFIG_EFM32_ADC
/* Some ADC peripheral must be enabled */
@@ -100,6 +102,7 @@
struct efm32_dev_s
{
FAR const struct adc_callback_s *cb;
uint8_t irq; /* Interrupt generated by this ADC block */
uint8_t nchannels; /* Number of channels */
uint8_t current; /* Current ADC channel being converted */
@@ -124,6 +127,8 @@ static int adc_interrupt(FAR struct adc_dev_s *dev);
/* ADC Driver Methods */
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void adc_reset(FAR struct adc_dev_s *dev);
static int adc_setup(FAR struct adc_dev_s *dev);
static void adc_shutdown(FAR struct adc_dev_s *dev);
@@ -148,6 +153,7 @@ static void adc_startconv(FAR struct efm32_dev_s *priv, bool enable);
static const struct adc_ops_s g_adcops =
{
.ao_bind = adc_bind,
.ao_reset = adc_reset,
.ao_setup = adc_setup,
.ao_shutdown = adc_shutdown,
@@ -790,7 +796,7 @@ static void adc_startconv(struct efm32_dev_s *priv, bool enable)
#endif
/****************************************************************************
* Name: adc_reset
* Name: adc_hw_reset
*
* Description:
* Deinitializes the ADCx peripheral registers to their default
@@ -873,6 +879,25 @@ static void adc_enable(FAR struct efm32_dev_s *priv, bool enable)
adc_putreg(priv, EFM32_ADC_CR2_OFFSET, regval);
}
/****************************************************************************
* Name: adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
FAR struct efm32_dev_s *priv = (FAR struct efm32_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: adc_reset
*
@@ -1180,14 +1205,21 @@ static int adc_interrupt(FAR struct adc_dev_s *dev)
value = adc_getreg(priv, EFM32_ADC_DR_OFFSET);
value &= ADC_DR_DATA_MASK;
/* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters:
*
* 1) The first is the ADC device instance for this ADC block.
* 2) The second is the channel number for the data, and
* 3) The third is the converted data for the channel.
*/
/* Verify that the upper-half driver has bound its callback functions */
adc_receive(dev, priv->chanlist[priv->current], value);
if (priv->cb != NULL)
{
/* Give the ADC data to the ADC driver. The ADC receive method
* accepts 3 parameters:
*
* 1) The first is the ADC device instance for this ADC block.
* 2) The second is the channel number for the data, and
* 3) The third is the converted data for the channel.
*/
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(dev, priv->chanlist[priv->current], value);
}
/* Set the channel number of the next channel that will complete conversion */
@@ -1272,7 +1304,8 @@ struct adc_dev_s *efm32_adcinitialize(int intf, const uint8_t *chanlist, int nch
/* Configure the selected ADC */
priv = dev->ad_priv;
priv = dev->ad_priv;
priv->cb = NULL;
DEBUGASSERT(nchannels <= ADC_MAX_SAMPLES);
priv->nchannels = nchannels;
@@ -1283,4 +1316,4 @@ struct adc_dev_s *efm32_adcinitialize(int intf, const uint8_t *chanlist, int nch
#endif /* CONFIG_EFM32_EFM32GG */
#endif /* CONFIG_EFM32_ADC1 */
#endif /* CONFIG_ADC */
#endif /* CONFIG_EFM32_ADC */
+2 -2
View File
@@ -74,7 +74,7 @@
#define IMX_CSPI1_SPIDMA (IMX_CSPI1_VBASE + CSPI_DMA_OFFSET)
#define IMX_CSPI1_SPIRESET (IMX_CSPI1_VBASE + CSPI_RESET_OFFSET)
/* CSPI1 */
/* CSPI2 */
#define IMX_CSPI2_RXD (IMX_CSPI2_VBASE + CSPI_RXD_OFFSET)
#define IMX_CSPI2_TXD (IMX_CSPI2_VBASE + CSPI_TXD_OFFSET)
@@ -138,7 +138,7 @@
/* CSPI Sample Period Control Register */
#define CSPI_SPCR_WAIT_SHIFT 0
#define CSPI_SPCR_WAIT_MASK (0x7ff << CSPI_CTRL_DATARATE_SHIFT)
#define CSPI_SPCR_WAIT_MASK (0x7ff << CSPI_SPCR_WAIT_SHIFT)
#define CSPI_SPCR_CSRC (1 << 15) /* Bit 15: 1:32768 or 32 kHz clock source */
/* CSPI DMA Control Register */
+29
View File
@@ -54,8 +54,37 @@ config IMX6_HAVE_HDCP
endmenu # "iMX.6 Chip Selection"
config IMX6_ECSPI
bool
default n
menu "iMX.6 Peripheral Selection"
config IMX6_ECSPI1
bool "ECSPI1"
default n
select IMX6_ECSPI
config IMX6_ECSPI2
bool "ECSPI2"
default n
select IMX6_ECSPI
config IMX6_ECSPI3
bool "ECSPI3"
default n
select IMX6_ECSPI
config IMX6_ECSPI4
bool "ECSPI4"
default n
select IMX6_ECSPI
config IMX6_ECSPI5
bool "ECSPI5"
default n
select IMX6_ECSPI
config IMX6_UART1
bool "UART1"
default n
+290
View File
@@ -0,0 +1,290 @@
/************************************************************************************
* arch/arm/src/imx6/imx_ecspi.h
*
* Copyright (C) 2009-2010, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __ARCH_ARM_IMX6_CHIP_ECSPI_H
#define __ARCH_ARM_IMX6_CHIP_ECSPI_H
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include "chip/imx_memorymap.h"
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* ECSPI Register Offsets ***********************************************************/
#define ECSPI_RXDATA_OFFSET 0x0000 /* Receive Data Register */
#define ECSPI_TXDATA_OFFSET 0x0004 /* Transmit Data Register */
#define ECSPI_CONREG_OFFSET 0x0008 /* Control Register */
#define ECSPI_CONFIGREG_OFFSET 0x000c /* Configuration Register */
#define ECSPI_INTREG_OFFSET 0x0010 /* Interrupt Control Register */
#define ECSPI_DMAREG_OFFSET 0x0014 /* DMA Control Register */
#define ECSPI_STATREG_OFFSET 0x0018 /* Status Register */
#define ECSPI_PERIODREG_OFFSET 0x001c /* Sample Period Control Register */
#define ECSPI_TESTREG_OFFSET 0x0020 /* Test Control Register */
#define ECSPI_MSGDATA_OFFSET 0x0040 /* Message Data Register */
/* ECSPI Register Addresses *********************************************************/
/* ECSPI1 */
#define IMX_ECSPI1_RXDATA (IMX_ECSPI1_VBASE + ECSPI_RXDATA_OFFSET)
#define IMX_ECSPI1_TXDATA (IMX_ECSPI1_VBASE + ECSPI_TXDATA_OFFSET)
#define IMX_ECSPI1_CONREG (IMX_ECSPI1_VBASE + ECSPI_CONREG_OFFSET)
#define IMX_ECSPI1_CONFIGREG (IMX_ECSPI1_VBASE + ECSPI_CONFIGREG_OFFSET)
#define IMX_ECSPI1_INTREG (IMX_ECSPI1_VBASE + ECSPI_INTREG_OFFSET)
#define IMX_ECSPI1_DMAREG (IMX_ECSPI1_VBASE + ECSPI_DMAREG_OFFSET)
#define IMX_ECSPI1_STATREG (IMX_ECSPI1_VBASE + ECSPI_STATREG_OFFSET)
#define IMX_ECSPI1_PERIODREG (IMX_ECSPI1_VBASE + ECSPI_PERIODREG_OFFSET)
#define IMX_ECSPI1_TESTREG (IMX_ECSPI1_VBASE + ECSPI_TESTREG_OFFSET)
#define IMX_ECSPI1_MSGDATA (IMX_ECSPI1_VBASE + ECSPI_MSGDATA_OFFSET)
/* ECSPI2 */
#define IMX_ECSPI2_RXDATA (IMX_ECSPI2_VBASE + ECSPI_RXDATA_OFFSET)
#define IMX_ECSPI2_TXDATA (IMX_ECSPI2_VBASE + ECSPI_TXDATA_OFFSET)
#define IMX_ECSPI2_CONREG (IMX_ECSPI2_VBASE + ECSPI_CONREG_OFFSET)
#define IMX_ECSPI2_CONFIGREG (IMX_ECSPI2_VBASE + ECSPI_CONFIGREG_OFFSET)
#define IMX_ECSPI2_INTREG (IMX_ECSPI2_VBASE + ECSPI_INTREG_OFFSET)
#define IMX_ECSPI2_DMAREG (IMX_ECSPI2_VBASE + ECSPI_DMAREG_OFFSET)
#define IMX_ECSPI2_STATREG (IMX_ECSPI2_VBASE + ECSPI_STATREG_OFFSET)
#define IMX_ECSPI2_PERIODREG (IMX_ECSPI2_VBASE + ECSPI_PERIODREG_OFFSET)
#define IMX_ECSPI2_TESTREG (IMX_ECSPI2_VBASE + ECSPI_TESTREG_OFFSET)
#define IMX_ECSPI2_MSGDATA (IMX_ECSPI2_VBASE + ECSPI_MSGDATA_OFFSET)
/* ECSPI3 */
#define IMX_ECSPI3_RXDATA (IMX_ECSPI3_VBASE + ECSPI_RXDATA_OFFSET)
#define IMX_ECSPI3_TXDATA (IMX_ECSPI3_VBASE + ECSPI_TXDATA_OFFSET)
#define IMX_ECSPI3_CONREG (IMX_ECSPI3_VBASE + ECSPI_CONREG_OFFSET)
#define IMX_ECSPI3_CONFIGREG (IMX_ECSPI3_VBASE + ECSPI_CONFIGREG_OFFSET)
#define IMX_ECSPI3_INTREG (IMX_ECSPI3_VBASE + ECSPI_INTREG_OFFSET)
#define IMX_ECSPI3_DMAREG (IMX_ECSPI3_VBASE + ECSPI_DMAREG_OFFSET)
#define IMX_ECSPI3_STATREG (IMX_ECSPI3_VBASE + ECSPI_STATREG_OFFSET)
#define IMX_ECSPI3_PERIODREG (IMX_ECSPI3_VBASE + ECSPI_PERIODREG_OFFSET)
#define IMX_ECSPI3_TESTREG (IMX_ECSPI3_VBASE + ECSPI_TESTREG_OFFSET)
#define IMX_ECSPI3_MSGDATA (IMX_ECSPI3_VBASE + ECSPI_MSGDATA_OFFSET)
/* ECSPI4 */
#define IMX_ECSPI4_RXDATA (IMX_ECSPI4_VBASE + ECSPI_RXDATA_OFFSET)
#define IMX_ECSPI4_TXDATA (IMX_ECSPI4_VBASE + ECSPI_TXDATA_OFFSET)
#define IMX_ECSPI4_CONREG (IMX_ECSPI4_VBASE + ECSPI_CONREG_OFFSET)
#define IMX_ECSPI4_CONFIGREG (IMX_ECSPI4_VBASE + ECSPI_CONFIGREG_OFFSET)
#define IMX_ECSPI4_INTREG (IMX_ECSPI4_VBASE + ECSPI_INTREG_OFFSET)
#define IMX_ECSPI4_DMAREG (IMX_ECSPI4_VBASE + ECSPI_DMAREG_OFFSET)
#define IMX_ECSPI4_STATREG (IMX_ECSPI4_VBASE + ECSPI_STATREG_OFFSET)
#define IMX_ECSPI4_PERIODREG (IMX_ECSPI4_VBASE + ECSPI_PERIODREG_OFFSET)
#define IMX_ECSPI4_TESTREG (IMX_ECSPI4_VBASE + ECSPI_TESTREG_OFFSET)
#define IMX_ECSPI4_MSGDATA (IMX_ECSPI4_VBASE + ECSPI_MSGDATA_OFFSET)
/* ECSPI5 */
#define IMX_ECSPI5_RXDATA (IMX_ECSPI5_VBASE + ECSPI_RXDATA_OFFSET)
#define IMX_ECSPI5_TXDATA (IMX_ECSPI5_VBASE + ECSPI_TXDATA_OFFSET)
#define IMX_ECSPI5_CONREG (IMX_ECSPI5_VBASE + ECSPI_CONREG_OFFSET)
#define IMX_ECSPI5_CONFIGREG (IMX_ECSPI5_VBASE + ECSPI_CONFIGREG_OFFSET)
#define IMX_ECSPI5_INTREG (IMX_ECSPI5_VBASE + ECSPI_INTREG_OFFSET)
#define IMX_ECSPI5_DMAREG (IMX_ECSPI5_VBASE + ECSPI_DMAREG_OFFSET)
#define IMX_ECSPI5_STATREG (IMX_ECSPI5_VBASE + ECSPI_STATREG_OFFSET)
#define IMX_ECSPI5_PERIODREG (IMX_ECSPI5_VBASE + ECSPI_PERIODREG_OFFSET)
#define IMX_ECSPI5_TESTREG (IMX_ECSPI5_VBASE + ECSPI_TESTREG_OFFSET)
#define IMX_ECSPI5_MSGDATA (IMX_ECSPI5_VBASE + ECSPI_MSGDATA_OFFSET)
/* ECSPI Register Bit Definitions ***************************************************/
/* Control Register */
#define ECSPI_CONREG_EN (1 << 0) /* Bit 0: SPI Block enable control */
#define ECSPI_CONREG_HT (1 << 1) /* Bit 1: Hardware trigger enable */
#define ECSPI_CONREG_XCH (1 << 2) /* Bit 2: SPI Exchange bit */
#define ECSPI_CONREG_SMC (1 << 3) /* Bit 3: Start mode control */
#define ECSPI_CONREG_CHMODE_SHIFT (4) /* Bits 4-7: SPI Channel mode */
#define ECSPI_CONREG_CHMODE_MASK (15 << ECSPI_CONREG_CHMODE_SHIFT)
# define ECSPI_CONREG_CH0MASTER (1 << ECSPI_CONREG_CHMODE_SHIFT) /* Channel 0 master mode */
# define ECSPI_CONREG_CH1MASTER (2 << ECSPI_CONREG_CHMODE_SHIFT) /* Channel 1 master mode */
# define ECSPI_CONREG_CH2MASTER (4 << ECSPI_CONREG_CHMODE_SHIFT) /* Channel 2 master mode */
# define ECSPI_CONREG_CH3MASTER (8 << ECSPI_CONREG_CHMODE_SHIFT) /* Channel 3 master mode */
#define ECSPI_CONREG_POSTDIV_SHIFT (8) /* Bits 8-11: SPI Post divider (exponent) */
#define ECSPI_CONREG_POSTDIV_MASK (15 << ECSPI_CONREG_POSTDIV_SHIFT)
# define ECSPI_CONREG_POSTDIV_EXP(n) ((uint32_t)(n) << ECSPI_CONREG_POSTDIV_SHIFT)
# define ECSPI_CONREG_POSTDIV_1 (0 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*0 */
# define ECSPI_CONREG_POSTDIV_2 (1 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*1 */
# define ECSPI_CONREG_POSTDIV_4 (2 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*2 */
# define ECSPI_CONREG_POSTDIV_8 (3 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*3 */
# define ECSPI_CONREG_POSTDIV_16 (4 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*4 */
# define ECSPI_CONREG_POSTDIV_32 (5 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*5 */
# define ECSPI_CONREG_POSTDIV_64 (6 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*6 */
# define ECSPI_CONREG_POSTDIV_128 (7 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*7 */
# define ECSPI_CONREG_POSTDIV_256 (8 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*8 */
# define ECSPI_CONREG_POSTDIV_512 (9 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*9 */
# define ECSPI_CONREG_POSTDIV_1024 (10 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*10 */
# define ECSPI_CONREG_POSTDIV_2048 (11 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*11 */
# define ECSPI_CONREG_POSTDIV_4096 (12 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*12 */
# define ECSPI_CONREG_POSTDIV_8192 (13 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*13 */
# define ECSPI_CONREG_POSTDIV_16384 (14 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*14 */
# define ECSPI_CONREG_POSTDIV_32768 (15 << ECSPI_CONREG_POSTDIV_SHIFT) /* Divide by 2*15 */
#define ECSPI_CONREG_PREDIV_SHIFT (12) /* Bits 12-15: SPI Pre divider (minus 1) */
#define ECSPI_CONREG_PREDIV_MASK (15 << ECSPI_CONREG_PREDIV_SHIFT)
# define ECSPI_CONREG_PREDIV(n) ((uint32_t)(n) << ECSPI_CONREG_PREDIV_SHIFT)
#define ECSPI_CONREG_DRCTL_SHIFT 16 /* Bits 16-17: SPI Data ready control */
#define ECSPI_CONREG_DRCTL_MASK (3 << ECSPI_CONREG_DRCTL_SHIFT)
# define ECSPI_CONREG_DRCTL_IGNRDY (0 << ECSPI_CONREG_DRCTL_SHIFT)
# define ECSPI_CONREG_DRCTL_FALLING (1 << ECSPI_CONREG_DRCTL_SHIFT)
# define ECSPI_CONREG_DRCTL_ACTVLOW (2 << ECSPI_CONREG_DRCTL_SHIFT)
#define ECSPI_CONREG_CHSEL_SHIFT (18) /* Bits 18-19: SPI Channel select bits */
#define ECSPI_CONREG_CHSEL_MASK (3 << ECSPI_CONREG_CHSEL_SHIFT)
# define ECSPI_CONREG_CHSEL_SS0 (0 << ECSPI_CONREG_CHSEL_SHIFT) /* Channel 0 select (SS0) */
# define ECSPI_CONREG_CHSEL_SS1 (1 << ECSPI_CONREG_CHSEL_SHIFT) /* Channel 1 select (SS1) */
# define ECSPI_CONREG_CHSEL_SS2 (2 << ECSPI_CONREG_CHSEL_SHIFT) /* Channel 2 select (SS2) */
# define ECSPI_CONREG_CHSEL_SS3 (3 << ECSPI_CONREG_CHSEL_SHIFT) /* Channel 3 select (SS3) */
#define ECSPI_CONREG_BURSTLEN_SHIFT (20) /* Bits 20-31: Burst length */
#define ECSPI_CONREG_BURSTLEN_MASK (0xfff << ECSPI_CONREG_BURSTLEN_SHIFT)
# define ECSPI_CONREG_BURSTLEN(n) ((uint32_t)(n) << ECSPI_CONREG_BURSTLEN_SHIFT)
/* Configuration Register */
#define ECSPI_CONFIGREG_SCLKPHA_SHIFT (0) /* Bits 0-3: SPI Clock/Data Phase Control */
#define ECSPI_CONFIGREG_SCLKPHA_MASK (15 << ECSPI_CONFIGREG_SCLKPHA_SHIFT)
# define ECSPI_CONFIGREG_CH0PHA (1 << ECSPI_CONFIGREG_SCLKPHA_SHIFT) /* Channel 0 SCLK Phase */
# define ECSPI_CONFIGREG_CH1PHA (2 << ECSPI_CONFIGREG_SCLKPHA_SHIFT) /* Channel 1 SCLK Phase */
# define ECSPI_CONFIGREG_CH2PHA (4 << ECSPI_CONFIGREG_SCLKPHA_SHIFT) /* Channel 2 SCLK Phase */
# define ECSPI_CONFIGREG_CH3PHA (8 << ECSPI_CONFIGREG_SCLKPHA_SHIFT) /* Channel 3 SCLK Phase */
#define ECSPI_CONFIGREG_SCLKPOL_SHIFT (4) /* Bits 4-7: SPI Clock polarity control */
#define ECSPI_CONFIGREG_SCLKPOL_MASK (15 << ECSPI_CONFIGREG_SCLKPOL_SHIFT)
# define ECSPI_CONFIGREG_CH0POL (1 << ECSPI_CONFIGREG_SCLKPOL_SHIFT) /* Channel 0 SCLK polarity */
# define ECSPI_CONFIGREG_CH1POL (2 << ECSPI_CONFIGREG_SCLKPOL_SHIFT) /* Channel 1 SCLK polarity */
# define ECSPI_CONFIGREG_CH2POL (4 << ECSPI_CONFIGREG_SCLKPOL_SHIFT) /* Channel 2 SCLK polarity */
# define ECSPI_CONFIGREG_CH3POL (8 << ECSPI_CONFIGREG_SCLKPOL_SHIFT) /* Channel 3 SCLK polarity */
#define ECSPI_CONFIGREG_SSCTL_SHIFT (8) /* Bits 8-11: SPI SS Wave form select */
#define ECSPI_CONFIGREG_SSCTL_MASK (15 << ECSPI_CONFIGREG_SSCTL_SHIFT)
# define ECSPI_CONFIGREG_CH0SSCTRL (1 << ECSPI_CONFIGREG_SSCTL_SHIFT) /* Channel 0 SS control */
# define ECSPI_CONFIGREG_CH1SSCTRL (2 << ECSPI_CONFIGREG_SSCTL_SHIFT) /* Channel 1 SS control */
# define ECSPI_CONFIGREG_CH2SSCTRL (4 << ECSPI_CONFIGREG_SSCTL_SHIFT) /* Channel 2 SS control */
# define ECSPI_CONFIGREG_CH3SSCTRL (8 << ECSPI_CONFIGREG_SSCTL_SHIFT) /* Channel 3 SS control */
#define ECSPI_CONFIGREG_SSPOL_SHIFT (12) /* Bits 12-15: SPI SS Polarity select */
#define ECSPI_CONFIGREG_SSPOL_MASK (15 << ECSPI_CONFIGREG_SSPOL_SHIFT)
# define ECSPI_CONFIGREG_CH0SSPOL (1 << ECSPI_CONFIGREG_CHMODE_SHIFT) /* Channel 0 SS polarity */
# define ECSPI_CONFIGREG_CH1SSPOL (2 << ECSPI_CONFIGREG_CHMODE_SHIFT) /* Channel 1 SS polarity */
# define ECSPI_CONFIGREG_CH2SSPOL (4 << ECSPI_CONFIGREG_CHMODE_SHIFT) /* Channel 2 SS polarity */
# define ECSPI_CONFIGREG_CH3SSPOL (8 << ECSPI_CONFIGREG_CHMODE_SHIFT) /* Channel 3 SS polarity */
#define ECSPI_CONFIGREG_DATCTL_SHIFT (16) /* Bits 16-19: Data control */
#define ECSPI_CONFIGREG_DATCTL_MASK (15 << ECSPI_CONFIGREG_DATCTL_SHIFT)
# define ECSPI_CONFIGREG_CH0DATLOW (1 << ECSPI_CONFIGREG_DATCTL_SHIFT) /* Channel 0 SS low when inactive */
# define ECSPI_CONFIGREG_CH1DATLOW (2 << ECSPI_CONFIGREG_DATCTL_SHIFT) /* Channel 1 SS low when inactive */
# define ECSPI_CONFIGREG_CH2DATLOW (4 << ECSPI_CONFIGREG_DATCTL_SHIFT) /* Channel 2 SS low when inactive */
# define ECSPI_CONFIGREG_CH3DATLOW (8 << ECSPI_CONFIGREG_DATCTL_SHIFT) /* Channel 3 SS low when inactive */
#define ECSPI_CONFIGREG_SCLKCTL_SHIFT (20) /* Bits 20-23: SCLK Control */
#define ECSPI_CONFIGREG_SCLKCTL_MASK (15 << ECSPI_CONFIGREG_SCLKCTL_SHIFT)
# define ECSPI_CONFIGREG_CH0SCLKLOW (1 << ECSPI_CONFIGREG_SCLKCTL_SHIFT) /* Channel 0 SCLK low when inactive */
# define ECSPI_CONFIGREG_CH1SCLKLOW (2 << ECSPI_CONFIGREG_SCLKCTL_SHIFT) /* Channel 1 SCLK low when inactive */
# define ECSPI_CONFIGREG_CH2SCLKLOW (4 << ECSPI_CONFIGREG_SCLKCTL_SHIFT) /* Channel 2 SCLK low when inactive */
# define ECSPI_CONFIGREG_CH3SCLKLOW (8 << ECSPI_CONFIGREG_SCLKCTL_SHIFT) /* Channel 3 SCLK low when inactive */
#define ECSPI_CONFIGREG_HTLEN_SHIFT (24) /* Bits 24-28: HT Length */
#define ECSPI_CONFIGREG_HTLEN_MASK (15 << ECSPI_CONFIGREG_HTLEN_SHIFT)
# define ECSPI_CONFIGREG_HTLEN(n) ((uint32_t)(n) << ECSPI_CONFIGREG_HTLEN_SHIFT)
/* Bits 29-31: Reserved */
/* Common Interrupt Control Register and Status Register */
#define ECSPI_INT_TE (1 << 0) /* Bit 0: TXFIFO Empty Interrupt */
#define ECSPI_INT_TDR (1 << 1) /* Bit 1: TXFIFO Data Request Interrupt */
#define ECSPI_INT_TF (1 << 2) /* Bit 2: TXFIFO Full Interrupt */
#define ECSPI_INT_RR (1 << 3) /* Bit 3: RXFIFO Data Ready Interrupt */
#define ECSPI_INT_RDR (1 << 4) /* Bit 4: RXFIFO Data Request Interrupt enable */
#define ECSPI_INT_RF (1 << 5) /* Bit 5: RXFIFO Full Interrupt */
#define ECSPI_INT_RO (1 << 6) /* Bit 6: RXFIFO Overflow Interrupt */
#define ECSPI_INT_TC (1 << 7) /* Bit 7: Transfer Completed Interrupt enable */
/* Bits 8-31: Reserved */
#define ECSPI_INT_ALL 0x000000ff
/* ECSPI DMA Control Register */
#define ECSPI_DMAREG_TXTHRES_SHIFT (0) /* Bits 0-5: TX Threshold */
#define ECSPI_DMAREG_TXTHRES_MASK (0x3f << ECSPI_DMAREG_TXTHRES_SHIFT)
# define ECSPI_DMAREG_TXTHRES(n) ((uint32_t)(n) << ECSPI_DMAREG_TXTHRES_SHIFT)
/* Bit 6: Reserved */
#define ECSPI_DMAREG_TEDEN (1 << 7) /* Bit 7: TXFIFO Empty DMA request enable */
/* Bits 8-15: Reserved */
#define ECSPI_DMAREG_RXTHRES_SHIFT (16) /* Bits 16-21: RX Threshold */
#define ECSPI_DMAREG_RXTHRES_MASK (0x3f << ECSPI_DMAREG_RXTHRES_SHIFT)
# define ECSPI_DMAREG_RXTHRES(n) ((uint32_t)(n) << ECSPI_DMAREG_RXTHRES_SHIFT)
/* Bit 22: Reserved */
#define ECSPI_DMAREG_RXDEN (1 << 23) /* Bit 23: RXFIFO DMA request enable */
#define ECSPI_DMAREG_RXLEN_SHIFT (24) /* Bits 24-29: RX DMA length */
#define ECSPI_DMAREG_RXLEN_MASK (0x3f << ECSPI_DMAREG_RXLEN_SHIFT)
# define ECSPI_DMAREG_RXLEN(n) ((uint32_t)(n) << ECSPI_DMAREG_RXLEN_SHIFT)
/* Bit 30: Reserved */
#define ECSPI_DMAREG_RXTDEN (1 << 31) /* Bit 31: RXFIFO Tail DMA request enable */
/* ECSPI Sample Period Control Register */
#define ECSPI_PERIODREG_PERIOD_SHIFT (0) /* Bits 0-14: Sample Period Control */
#define ECSPI_PERIODREG_PERIOD_MASK (0x7fff << ECSPI_PERIODREG_PERIOD_SHIFT)
# define ECSPI_PERIODREG_PERIOD(n) ((uint32_t)(n) << ECSPI_PERIODREG_PERIOD_SHIFT)
#define ECSPI_PERIODREG_CSRC (1 << 15) /* Bit 15: Clock source control */
#define ECSPI_PERIODREG_CSDCTL_SHIFT (16) /* Bits 16-21: Chip Select delay control */
#define ECSPI_PERIODREG_CSDCTL_MASK (0x3f << ECSPI_PERIODREG_CSDCTL_SHIFT)
# define ECSPI_PERIODREG_CSDCTL(n) ((uint32_t)(n) << ECSPI_PERIODREG_CSDCTL_SHIFT)
/* Bits 22-31: Reserved */
/* Test Control Register */
#define ECSPI_TESTREG_TXCNT_SHIFT (0) /* Bits 0-6: TXFIFO Counter */
#define ECSPI_TESTREG_TXCNT_MASK (0x7f << ECSPI_TESTREG_TXCNT_SHIFT)
# define ECSPI_TESTREG_TXCNT(n) ((uint32_t)(n) << ECSPI_TESTREG_TXCNT_SHIFT)
/* Bit 7: Reserved */
#define ECSPI_TESTREG_RXCNT_SHIFT (8) /* Bits 8-14: RXFIFO Counter */
#define ECSPI_TESTREG_RXCNT_MASK (0x7f << ECSPI_TESTREG_RXCNT_SHIFT)
# define ECSPI_TESTREG_RXCNT(n) ((uint32_t)(n) << ECSPI_TESTREG_RXCNT_SHIFT)
/* Bits 15-30: Reserved */
#define ECSPI_TESTREG_LBC (1 << 31) /* Bit 31: Loop Back Control */
/* Message Data Register (32-bit message data) */
/************************************************************************************
* Public Data
************************************************************************************/
/************************************************************************************
* Public Function Prototypes
************************************************************************************/
#endif /* __ARCH_ARM_IMX6_CHIP_ECSPI_H */
+166
View File
@@ -0,0 +1,166 @@
/************************************************************************************
* arch/arm/src/imx6/imx_ecspi.h
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __ARCH_ARM_IMX6_ECSPI_H
#define __ARCH_ARM_IMX6_ECSPI_H
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/spi/spi.h>
#include "chip/imx_ecspi.h"
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/************************************************************************************
* Public Data
************************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif /* __cplusplus */
/************************************************************************************
* Public Function Prototypes
************************************************************************************/
struct spi_dev_s; /* Forward reference */
enum spi_dev_e; /* Forward reference */
/************************************************************************************
* Name: imx_spibus_initialize
*
* Description:
* Initialize common parts the selected SPI port. Initialization of
* chip select GPIOs must have been performed by board specific logic
* prior to calling this function. Specifically: GPIOs should have
* been configured for output, and all chip selects disabled.
*
* One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select. However,
* If multiple devices on on the bus, then multiple chip selects will be
* required. Theregore, all GPIO chip management is deferred to board-
* specific logic.
*
* Input Parameter:
* Port number (for hardware that has mutiple SPI interfaces)
*
* Returned Value:
* Valid SPI device structre reference on succcess; a NULL on failure
*
************************************************************************************/
FAR struct spi_dev_s *imx_spibus_initialize(int port);
/************************************************************************************
* The external functions, imx_spiselect, imx_spistatus, and imx_cmddaa must be
* provided by board-specific logic. These are implementations of the select and
* status methods of the SPI interface defined by struct spi_ops_s (see
* include/nuttx/spi/spi.h). All other methods (including imx_spibus_initialize()) are
* provided by common logic. To use this common SPI logic on your board:
*
* 1. Provide imx_spiselect() and imx_spistatus() functions in your board-specific
* logic. This function will perform chip selection and status operations using
* GPIOs in the way your board is configured.
* 2. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration, provide the
* imx_spicmddata() function in your board-specific logic. This function will
* perform cmd/data selection operations using GPIOs in the way your board is
* configured.
* 3. Add a call to imx_spibus_initialize() in your low level initialization logic
* 4. The handle returned by imx_spibus_initialize() may then be used to bind the
* SPI driver to higher level logic (e.g., calling mmcsd_spislotinitialize(),
* for example, will bind the SPI driver to the SPI MMC/SD driver).
*
************************************************************************************/
#ifdef CONFIG_IMX6_ECSPI1
void imx_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
uint8_t imx_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
#ifdef CONFIG_SPI_CMDDATA
int imx_spi1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
#ifdef CONFIG_IMX6_ECSPI2
void imx_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
uint8_t imx_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
#ifdef CONFIG_SPI_CMDDATA
int imx_spi2cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
#ifdef CONFIG_IMX6_ECSPI3
void imx_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
uint8_t imx_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
#ifdef CONFIG_SPI_CMDDATA
int imx_spi3cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
#ifdef CONFIG_IMX6_ECSPI4
void imx_spi4select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
uint8_t imx_spi4status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
#ifdef CONFIG_SPI_CMDDATA
int imx_spi4cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
#ifdef CONFIG_IMX6_ECSPI5
void imx_spi5select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
uint8_t imx_spi5status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
#ifdef CONFIG_SPI_CMDDATA
int imx_spi5cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_IMX6_ECSPI_H */
+59 -11
View File
@@ -2,8 +2,9 @@
* arch/arm/src/lpc17xx/lpc17_adc.c
*
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-05 initial version
* Gregory Nutt <gnutt@nuttx.org>
*
* This file is a part of NuttX:
*
@@ -50,6 +51,7 @@
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
@@ -87,6 +89,7 @@
struct up_dev_s
{
FAR const struct adc_callback_s *cb;
uint8_t mask;
uint32_t sps;
int irq;
@@ -98,8 +101,12 @@ struct up_dev_s
* Private Function Prototypes
****************************************************************************/
static void adc_receive(FAR struct up_dev_s *priv, uint8_t ch, int32_t data);
/* ADC methods */
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void adc_reset(FAR struct adc_dev_s *dev);
static int adc_setup(FAR struct adc_dev_s *dev);
static void adc_shutdown(FAR struct adc_dev_s *dev);
@@ -113,6 +120,7 @@ static int adc_interrupt(int irq, void *context);
static const struct adc_ops_s g_adcops =
{
.ao_bind = adc_bind,
.ao_reset = adc_reset,
.ao_setup = adc_setup,
.ao_shutdown = adc_shutdown,
@@ -137,6 +145,46 @@ static struct adc_dev_s g_adcdev =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: adc_receive
*
* Description:
* Provide received ADC dat to the upper-half driver.
*
****************************************************************************/
static void adc_receive(FAR struct up_dev_s *priv, uint8_t ch, int32_t data)
{
/* Verify that the upper-half driver has bound its callback functions. */
if (priv->cb != NULL)
{
/* Perform the data received callback */
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(&g_adcdev, ch, data);
}
}
/****************************************************************************
* Name: adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: adc_reset
*
@@ -384,7 +432,7 @@ static int adc_interrupt(int irq, void *context)
{
value = priv->buf[ch] / priv->count[ch];
value <<= 15;
adc_receive(&g_adcdev, ch, value);
adc_receive(priv, ch, value);
priv->buf[ch] = 0;
priv->count[ch] = 0;
}
@@ -409,7 +457,7 @@ static int adc_interrupt(int irq, void *context)
{
value = priv->buf[ch] / priv->count[ch];
value <<= 15;
adc_receive(&g_adcdev, ch, value);
adc_receive(priv, ch, value);
priv->buf[ch] = 0;
priv->count[ch] = 0;
}
@@ -446,7 +494,7 @@ static int adc_interrupt(int irq, void *context)
#else /* CONFIG_ADC_WORKER_THREAD */
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 0, (regVal >> 4) & 0xFFF);
adc_receive(priv, 0, (regVal >> 4) & 0xFFF);
}
#endif /* CONFIG_ADC_WORKER_THREAD */
@@ -473,7 +521,7 @@ static int adc_interrupt(int irq, void *context)
#else /* CONFIG_ADC_WORKER_THREAD */
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 1, (regVal >> 4) & 0xFFF);
adc_receive(priv, 1, (regVal >> 4) & 0xFFF);
}
#endif /* CONFIG_ADC_WORKER_THREAD */
@@ -500,7 +548,7 @@ static int adc_interrupt(int irq, void *context)
#else /* CONFIG_ADC_WORKER_THREAD */
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 2, (regVal >> 4) & 0xFFF);
adc_receive(priv, 2, (regVal >> 4) & 0xFFF);
}
#endif /* CONFIG_ADC_WORKER_THREAD */
@@ -512,7 +560,7 @@ static int adc_interrupt(int irq, void *context)
regVal = getreg32(LPC17_ADC_DR3);
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 3, (regVal >> 4) & 0xFFF);
adc_receive(priv, 3, (regVal >> 4) & 0xFFF);
}
}
@@ -521,7 +569,7 @@ static int adc_interrupt(int irq, void *context)
regVal = getreg32(LPC17_ADC_DR4);
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 4, (regVal >> 4) & 0xFFF);
adc_receive(priv, 4, (regVal >> 4) & 0xFFF);
}
}
@@ -530,7 +578,7 @@ static int adc_interrupt(int irq, void *context)
regVal = getreg32(LPC17_ADC_DR5);
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 5, (regVal >> 4) & 0xFFF);
adc_receive(priv, 5, (regVal >> 4) & 0xFFF);
}
}
@@ -539,7 +587,7 @@ static int adc_interrupt(int irq, void *context)
regVal = getreg32(LPC17_ADC_DR6);
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 6, (regVal >> 4) & 0xFFF);
adc_receive(priv, 6, (regVal >> 4) & 0xFFF);
}
}
@@ -548,7 +596,7 @@ static int adc_interrupt(int irq, void *context)
regVal = getreg32(LPC17_ADC_DR7);
if ((regVal) & (1 << 31))
{
adc_receive(&g_adcdev, 7, (regVal >> 4) & 0xFFF);
adc_receive(priv, 7, (regVal >> 4) & 0xFFF);
}
}
+39 -2
View File
@@ -7,8 +7,9 @@
* Ported from from the LPC17 version:
*
* Copyright(C) 2011 Li Zhuoyi. All rights reserved.
* Copyright(C) 2016 Gregory Nutt. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-05 initial version
* Gregory Nutt
*
* This file is a part of NuttX:
*
@@ -55,6 +56,7 @@
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
@@ -112,6 +114,7 @@
struct up_dev_s
{
FAR const struct adc_callback_s *cb;
uint8_t mask;
uint8_t mask_int;
uint32_t freq;
@@ -126,6 +129,8 @@ struct up_dev_s
/* ADC methods */
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void adc_reset(FAR struct adc_dev_s *dev);
static int adc_setup(FAR struct adc_dev_s *dev);
static void adc_shutdown(FAR struct adc_dev_s *dev);
@@ -139,6 +144,7 @@ static int adc_interrupt(int irq, void *context);
static const struct adc_ops_s g_adcops =
{
.ao_bind = adc_bind,
.ao_reset = adc_reset,
.ao_setup = adc_setup,
.ao_shutdown = adc_shutdown,
@@ -166,6 +172,25 @@ static struct adc_dev_s g_adcdev =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: adc_reset
*
@@ -454,8 +479,20 @@ static int adc_interrupt(int irq, void *context)
{
if (priv->mask & (1 << i))
{
int32_t data;
regval = getreg32(LPC43_ADC0_DR(i));
adc_receive(&g_adcdev, i,(regval&ADC_DR_VVREF_MASK)>>ADC_DR_VVREF_SHIFT);
data = (regval & ADC_DR_VVREF_MASK) >> ADC_DR_VVREF_SHIFT;
/* Verify that the upper-half driver has bound its callback functions */
if (priv->cb != NULL)
{
/* Perform the data received callback */
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(&g_adcdev, i, data);
}
}
}
+1
View File
@@ -1060,6 +1060,7 @@ config SAM34_TC5_TIOB
config SAM34_ONESHOT
bool "TC one-shot wrapper"
depends on SAM34_FREERUN
default n if !SCHED_TICKLESS
default y if SCHED_TICKLESS
---help---
+55 -12
View File
@@ -58,6 +58,7 @@
#include <nuttx/clock.h>
#include "sam4cm_oneshot.h"
#include "sam4cm_freerun.h"
#ifdef CONFIG_SAM34_ONESHOT
@@ -106,10 +107,11 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
/* Forward the event, clearing out any vestiges */
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot->start_count = 0;
oneshot_handler(oneshot_arg);
}
@@ -206,10 +208,11 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
* success.
*/
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->start_count = 0;
return OK;
}
@@ -248,8 +251,8 @@ int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec)
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts)
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts)
{
uint64_t usec;
uint64_t regval;
@@ -267,7 +270,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
/* Yes.. then cancel it */
tcvdbg("Already running... cancelling\n");
(void)sam_oneshot_cancel(oneshot, NULL);
(void)sam_oneshot_cancel(oneshot, freerun, NULL);
}
/* Save the new handler and its argument */
@@ -306,6 +309,26 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
sam_tc_start(oneshot->tch);
/* The function sam_tc_start() starts the timer/counter by setting the
* bits TC_CCR_CLKEN and TC_CCR_SWTRG in the channel control register.
* The first one enables the timer/counter the latter performs an
* software trigger, which starts the clock and sets the counter
* register to zero. This reset is performed with the next valid edge
* of the selected clock. Thus it can take up USEC_PER_TICK microseconds
* until the counter register becomes zero.
*
* If the timer is canceled within this period the counter register holds
* the counter value for the last timer/counter run. To circumvent this
* the counter value of the freerun timer/counter is stored at each start
* of the oneshot timer/counter.
*
* The function up_timer_gettime() could also be used for this but it takes
* too long. If up_timer_gettime() is called within this function the problem
* vanishes at least if compiled with no optimisation.
*/
oneshot->start_count = sam_tc_getcounter(freerun->tch);
/* Enable interrupts. We should get the callback when the interrupt
* occurs.
*/
@@ -340,7 +363,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts)
{
irqstate_t flags;
uint64_t usec;
@@ -381,6 +405,17 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
count = sam_tc_getcounter(oneshot->tch);
rc = sam_tc_getregister(oneshot->tch, TC_REGC);
/* In the case the timer/counter was canceled very short after its start,
* the counter register can hold the wrong value (the value of the last
* run). To prevent this the counter value is set to zero if not at
* least on tick passed since the start of the timer/counter.
*/
if (count > 0 && sam_tc_getcounter(freerun->tch) == oneshot->start_count)
{
count = 0;
}
/* Now we can disable the interrupt and stop the timer. */
sam_tc_attach(oneshot->tch, NULL, NULL, 0);
@@ -429,6 +464,14 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
usec = (((uint64_t)(rc - count)) * USEC_PER_SEC) /
sam_tc_divfreq(oneshot->tch);
/* Each time the timer/counter is canceled the time calculated from
* the two registers (counter and REGC) is accurate up to an error
* between 0 and USEC_PER_TICK microseconds. To correct this error
* one tick which means USEC_PER_TICK microseconds are subtracted.
*/
usec = usec > USEC_PER_TICK ? usec - USEC_PER_TICK : 0;
/* Return the time remaining in the correct form */
sec = usec / USEC_PER_SEC;
+16 -3
View File
@@ -46,6 +46,7 @@
#include <time.h>
#include "sam4cm_tc.h"
#include "sam4cm_freerun.h"
#ifdef CONFIG_SAM34_ONESHOT
@@ -82,6 +83,11 @@ struct sam_oneshot_s
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* The argument that will accompany
* the callback */
volatile uint32_t start_count; /* Stores the value of the freerun counter,
* at each start of the onshot timer. Is neccesary
* to find out if the onshot counter was updated
* correctly at the time of the call to
* sam_oneshot_cancel or not. */
};
/****************************************************************************
@@ -136,6 +142,9 @@ int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec);
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
@@ -146,8 +155,8 @@ int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec);
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts);
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts);
/****************************************************************************
* Name: sam_oneshot_cancel
@@ -162,6 +171,9 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
@@ -173,7 +185,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts);
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts);
#undef EXTERN
#ifdef __cplusplus
+3 -3
View File
@@ -365,8 +365,8 @@ int up_timer_gettime(FAR struct timespec *ts)
int up_timer_cancel(FAR struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_cancel(&g_tickless.oneshot, ts) :
return ONESHOT_INITIALIZED(&g_tickless.oneshot) && FREERUN_INITIALIZED(&g_tickless.freerun) ?
sam_oneshot_cancel(&g_tickless.oneshot, &g_tickless.freerun, ts) :
-EAGAIN;
}
@@ -398,7 +398,7 @@ int up_timer_cancel(FAR struct timespec *ts)
int up_timer_start(FAR const struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_start(&g_tickless.oneshot, sam_oneshot_handler, NULL, ts) :
sam_oneshot_start(&g_tickless.oneshot, &g_tickless.freerun, sam_oneshot_handler, NULL, ts) :
-EAGAIN;
}
#endif /* CONFIG_SCHED_TICKLESS */
+1
View File
@@ -3866,6 +3866,7 @@ endif # SAMA5_TC2
config SAMA5_ONESHOT
bool "TC one-shot wrapper"
depends on SAMA5_FREERUN
default n if !SCHED_TICKLESS
default y if SCHED_TICKLESS
---help---
+45 -3
View File
@@ -57,6 +57,7 @@
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
@@ -378,6 +379,7 @@
struct sam_adc_s
{
FAR const struct adc_callback_s *cb;
sem_t exclsem; /* Supports exclusive access to the ADC interface */
bool initialized; /* The ADC driver is already initialized */
uint32_t frequency; /* ADC clock frequency */
@@ -446,6 +448,8 @@ static int sam_adc_interrupt(int irq, void *context);
/* ADC methods */
#ifdef SAMA5_ADC_HAVE_CHANNELS
static int sam_adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void sam_adc_reset(struct adc_dev_s *dev);
static int sam_adc_setup(struct adc_dev_s *dev);
static void sam_adc_shutdown(struct adc_dev_s *dev);
@@ -477,6 +481,7 @@ static void sam_adc_channels(struct sam_adc_s *priv);
static const struct adc_ops_s g_adcops =
{
.ao_bind = sam_adc_bind,
.ao_reset = sam_adc_reset,
.ao_setup = sam_adc_setup,
.ao_shutdown = sam_adc_shutdown,
@@ -664,9 +669,15 @@ static void sam_adc_dmadone(void *arg)
chan = (int)((*buffer & ADC_LCDR_CHANB_MASK) >> ADC_LCDR_CHANB_SHIFT);
sample = ((*buffer & ADC_LCDR_DATA_MASK) >> ADC_LCDR_DATA_SHIFT);
/* And give the sample data to the ADC upper half */
/* Verify that the upper-half driver has bound its callback functions */
(void)adc_receive(priv->dev, chan, sample);
if (priv->cb != NULL)
{
/* Give the sample data to the ADC upper half */
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(priv->dev, chan, sample);
}
}
}
@@ -858,7 +869,17 @@ static void sam_adc_endconversion(void *arg)
/* Read the ADC sample and pass it to the upper half */
regval = sam_adc_getreg(priv, SAM_ADC_CDR(chan));
(void)adc_receive(priv->dev, chan, regval & ADC_CDR_DATA_MASK);
/* Verify that the upper-half driver has bound its callback functions */
if (priv->cb != NULL)
{
/* Perform the data received callback */
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(priv->dev, chan, regval & ADC_CDR_DATA_MASK);
}
pending &= ~bit;
}
}
@@ -954,6 +975,26 @@ static int sam_adc_interrupt(int irq, void *context)
/****************************************************************************
* ADC methods
****************************************************************************/
/****************************************************************************
* Name: sam_adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int sam_adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: sam_adc_reset
*
@@ -1980,6 +2021,7 @@ struct adc_dev_s *sam_adc_initialize(void)
/* Initialize the private ADC device data structure */
sem_init(&priv->exclsem, 0, 1);
priv->cb = NULL;
priv->dev = &g_adcdev;
#ifdef CONFIG_SAMA5_ADC_DMA
+55 -12
View File
@@ -59,6 +59,7 @@
#include <nuttx/clock.h>
#include "sam_oneshot.h"
#include "sam_freerun.h"
#ifdef CONFIG_SAMA5_ONESHOT
@@ -123,10 +124,11 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
/* Forward the event, clearing out any vestiges */
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot->start_count = 0;
oneshot_handler(oneshot_arg);
}
@@ -223,10 +225,11 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
* success.
*/
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->start_count = 0;
return OK;
}
@@ -250,8 +253,8 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts)
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts)
{
uint64_t usec;
uint64_t regval;
@@ -269,7 +272,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
/* Yes.. then cancel it */
tcvdbg("Already running... cancelling\n");
(void)sam_oneshot_cancel(oneshot, NULL);
(void)sam_oneshot_cancel(oneshot, freerun, NULL);
}
/* Save the new handler and its argument */
@@ -308,6 +311,26 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
sam_tc_start(oneshot->tch);
/* The function sam_tc_start() starts the timer/counter by setting the
* bits TC_CCR_CLKEN and TC_CCR_SWTRG in the channel control register.
* The first one enables the timer/counter the latter performs an
* software trigger, which starts the clock and sets the counter
* register to zero. This reset is performed with the next valid edge
* of the selected clock. Thus it can take up USEC_PER_TICK microseconds
* until the counter register becomes zero.
*
* If the timer is canceled within this period the counter register holds
* the counter value for the last timer/counter run. To circumvent this
* the counter value of the freerun timer/counter is stored at each start
* of the oneshot timer/counter.
*
* The function up_timer_gettime() could also be used for this but it takes
* too long. If up_timer_gettime() is called within this function the problem
* vanishes at least if compiled with no optimisation.
*/
oneshot->start_count = sam_tc_getcounter(freerun->tch);
/* Enable interrupts. We should get the callback when the interrupt
* occurs.
*/
@@ -342,7 +365,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts)
{
irqstate_t flags;
uint64_t usec;
@@ -383,6 +407,17 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
count = sam_tc_getcounter(oneshot->tch);
rc = sam_tc_getregister(oneshot->tch, TC_REGC);
/* In the case the timer/counter was canceled very short after its start,
* the counter register can hold the wrong value (the value of the last
* run). To prevent this the counter value is set to zero if not at
* least on tick passed since the start of the timer/counter.
*/
if (count > 0 && sam_tc_getcounter(freerun->tch) == oneshot->start_count)
{
count = 0;
}
/* Now we can disable the interrupt and stop the timer. */
sam_tc_attach(oneshot->tch, NULL, NULL, 0);
@@ -431,6 +466,14 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
usec = (((uint64_t)(rc - count)) * USEC_PER_SEC) /
sam_tc_divfreq(oneshot->tch);
/* Each time the timer/counter is canceled the time calculated from
* the two registers (counter and REGC) is accurate up to an error
* between 0 and USEC_PER_TICK microseconds. To correct this error
* one tick which means USEC_PER_TICK microseconds are subtracted.
*/
usec = usec > USEC_PER_TICK ? usec - USEC_PER_TICK : 0;
/* Return the time remaining in the correct form */
sec = usec / USEC_PER_SEC;
+16 -3
View File
@@ -46,6 +46,7 @@
#include <time.h>
#include "sam_tc.h"
#include "sam_freerun.h"
#ifdef CONFIG_SAMA5_ONESHOT
@@ -82,6 +83,11 @@ struct sam_oneshot_s
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* The argument that will accompany
* the callback */
volatile uint32_t start_count; /* Stores the value of the freerun counter,
* at each start of the onshot timer. Is neccesary
* to find out if the onshot counter was updated
* correctly at the time of the call to
* sam_oneshot_cancel or not. */
};
/****************************************************************************
@@ -134,6 +140,9 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
@@ -144,8 +153,8 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts);
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts);
/****************************************************************************
* Name: sam_oneshot_cancel
@@ -160,6 +169,9 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
@@ -171,7 +183,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts);
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts);
#undef EXTERN
#ifdef __cplusplus
+3 -3
View File
@@ -377,8 +377,8 @@ int up_timer_gettime(FAR struct timespec *ts)
int up_timer_cancel(FAR struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_cancel(&g_tickless.oneshot, ts) :
return ONESHOT_INITIALIZED(&g_tickless.oneshot) && FREERUN_INITIALIZED(&g_tickless.freerun) ?
sam_oneshot_cancel(&g_tickless.oneshot, &g_tickless.freerun, ts) :
-EAGAIN;
}
@@ -410,7 +410,7 @@ int up_timer_cancel(FAR struct timespec *ts)
int up_timer_start(FAR const struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_start(&g_tickless.oneshot, sam_oneshot_handler, NULL, ts) :
sam_oneshot_start(&g_tickless.oneshot, &g_tickless.freerun, sam_oneshot_handler, NULL, ts) :
-EAGAIN;
}
#endif /* CONFIG_SCHED_TICKLESS */
+1
View File
@@ -1514,6 +1514,7 @@ endif # SAMV7_TC3
config SAMV7_ONESHOT
bool "TC one-shot wrapper"
depends on SAMV7_FREERUN
default n if !SCHED_TICKLESS
default y if SCHED_TICKLESS
---help---
+55 -12
View File
@@ -60,6 +60,7 @@
#include <nuttx/clock.h>
#include "sam_oneshot.h"
#include "sam_freerun.h"
#ifdef CONFIG_SAMV7_ONESHOT
@@ -124,10 +125,11 @@ static void sam_oneshot_handler(TC_HANDLE tch, void *arg, uint32_t sr)
/* Forward the event, clearing out any vestiges */
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot_handler = (oneshot_handler_t)oneshot->handler;
oneshot->handler = NULL;
oneshot_arg = (void *)oneshot->arg;
oneshot->arg = NULL;
oneshot->start_count = 0;
oneshot_handler(oneshot_arg);
}
@@ -224,10 +226,11 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
* success.
*/
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->chan = chan;
oneshot->running = false;
oneshot->handler = NULL;
oneshot->arg = NULL;
oneshot->start_count = 0;
return OK;
}
@@ -251,8 +254,8 @@ int sam_oneshot_initialize(struct sam_oneshot_s *oneshot, int chan,
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts)
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts)
{
uint64_t usec;
uint64_t regval;
@@ -270,7 +273,7 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
/* Yes.. then cancel it */
tcvdbg("Already running... cancelling\n");
(void)sam_oneshot_cancel(oneshot, NULL);
(void)sam_oneshot_cancel(oneshot, freerun, NULL);
}
/* Save the new handler and its argument */
@@ -309,6 +312,26 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
sam_tc_start(oneshot->tch);
/* The function sam_tc_start() starts the timer/counter by setting the
* bits TC_CCR_CLKEN and TC_CCR_SWTRG in the channel control register.
* The first one enables the timer/counter the latter performs an
* software trigger, which starts the clock and sets the counter
* register to zero. This reset is performed with the next valid edge
* of the selected clock. Thus it can take up USEC_PER_TICK microseconds
* until the counter register becomes zero.
*
* If the timer is canceled within this period the counter register holds
* the counter value for the last timer/counter run. To circumvent this
* the counter value of the freerun timer/counter is stored at each start
* of the oneshot timer/counter.
*
* The function up_timer_gettime() could also be used for this but it takes
* too long. If up_timer_gettime() is called within this function the problem
* vanishes at least if compiled with no optimisation.
*/
oneshot->start_count = sam_tc_getcounter(freerun->tch);
/* Enable interrupts. We should get the callback when the interrupt
* occurs.
*/
@@ -343,7 +366,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts)
{
irqstate_t flags;
uint64_t usec;
@@ -384,6 +408,17 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
count = sam_tc_getcounter(oneshot->tch);
rc = sam_tc_getregister(oneshot->tch, TC_REGC);
/* In the case the timer/counter was canceled very short after its start,
* the counter register can hold the wrong value (the value of the last
* run). To prevent this the counter value is set to zero if not at
* least on tick passed since the start of the timer/counter.
*/
if (count > 0 && sam_tc_getcounter(freerun->tch) == oneshot->start_count)
{
count = 0;
}
/* Now we can disable the interrupt and stop the timer. */
sam_tc_attach(oneshot->tch, NULL, NULL, 0);
@@ -432,6 +467,14 @@ int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts)
usec = (((uint64_t)(rc - count)) * USEC_PER_SEC) /
sam_tc_divfreq(oneshot->tch);
/* Each time the timer/counter is canceled the time calculated from
* the two registers (counter and REGC) is accurate up to an error
* between 0 and USEC_PER_TICK microseconds. To correct this error
* one tick which means USEC_PER_TICK microseconds are subtracted.
*/
usec = usec > USEC_PER_TICK ? usec - USEC_PER_TICK : 0;
/* Return the time remaining in the correct form */
sec = usec / USEC_PER_SEC;
+16 -3
View File
@@ -46,6 +46,7 @@
#include <time.h>
#include "sam_tc.h"
#include "sam_freerun.h"
#ifdef CONFIG_SAMV7_ONESHOT
@@ -82,6 +83,11 @@ struct sam_oneshot_s
volatile oneshot_handler_t handler; /* Oneshot expiration callback */
volatile void *arg; /* The argument that will accompany
* the callback */
volatile uint32_t start_count; /* Stores the value of the freerun counter,
* at each start of the onshot timer. Is neccesary
* to find out if the onshot counter was updated
* correctly at the time of the call to
* sam_oneshot_cancel or not. */
};
/****************************************************************************
@@ -157,6 +163,9 @@ int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec);
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* handler The function to call when when the oneshot timer expires.
* arg An opaque argument that will accompany the callback.
* ts Provides the duration of the one shot timer.
@@ -167,8 +176,8 @@ int sam_oneshot_max_delay(struct sam_oneshot_s *oneshot, uint64_t *usec);
*
****************************************************************************/
int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
void *arg, const struct timespec *ts);
int sam_oneshot_start(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
oneshot_handler_t handler, void *arg, const struct timespec *ts);
/****************************************************************************
* Name: sam_oneshot_cancel
@@ -183,6 +192,9 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
* oneshot Caller allocated instance of the oneshot state structure. This
* structure must have been previously initialized via a call to
* sam_oneshot_initialize();
* freerun Caller allocated instance of the freerun state structure. This
* structure must have been previously initialized via a call to
* sam_freerun_initialize();
* ts The location in which to return the time remaining on the
* oneshot timer. A time of zero is returned if the timer is
* not running.
@@ -194,7 +206,8 @@ int sam_oneshot_start(struct sam_oneshot_s *oneshot, oneshot_handler_t handler,
*
****************************************************************************/
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct timespec *ts);
int sam_oneshot_cancel(struct sam_oneshot_s *oneshot, struct sam_freerun_s *freerun,
struct timespec *ts);
#undef EXTERN
#ifdef __cplusplus
+3 -3
View File
@@ -363,8 +363,8 @@ int up_timer_gettime(FAR struct timespec *ts)
int up_timer_cancel(FAR struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_cancel(&g_tickless.oneshot, ts) :
return ONESHOT_INITIALIZED(&g_tickless.oneshot) && FREERUN_INITIALIZED(&g_tickless.freerun) ?
sam_oneshot_cancel(&g_tickless.oneshot, &g_tickless.freerun, ts) :
-EAGAIN;
}
@@ -396,7 +396,7 @@ int up_timer_cancel(FAR struct timespec *ts)
int up_timer_start(FAR const struct timespec *ts)
{
return ONESHOT_INITIALIZED(&g_tickless.oneshot) ?
sam_oneshot_start(&g_tickless.oneshot, sam_oneshot_handler, NULL, ts) :
sam_oneshot_start(&g_tickless.oneshot, &g_tickless.freerun, sam_oneshot_handler, NULL, ts) :
-EAGAIN;
}
#endif /* CONFIG_SCHED_TICKLESS */
+1 -1
View File
@@ -203,7 +203,7 @@ CHIP_CSRCS += stm32_rtc_lowerhalf.c
endif
endif
ifeq ($(CONFIG_ADC),y)
ifeq ($(CONFIG_STM32_ADC),y)
CHIP_CSRCS += stm32_adc.c
endif
+6 -2
View File
@@ -628,7 +628,8 @@
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469) || \
defined(CONFIG_STM32_STM32F411)
# define GPIO_SPI4_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTE|GPIO_PIN5)
# define GPIO_SPI4_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTE|GPIO_PIN13)
# define GPIO_SPI4_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTE|GPIO_PIN6)
@@ -643,7 +644,7 @@
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F469) || defined(CONFIG_STM32_STM32F411)
# define GPIO_SPI5_MISO_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTF|GPIO_PIN8)
# define GPIO_SPI5_MISO_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTH|GPIO_PIN7)
# define GPIO_SPI5_MOSI_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTF|GPIO_PIN9)
@@ -652,7 +653,10 @@
# define GPIO_SPI5_NSS_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTH|GPIO_PIN5)
# define GPIO_SPI5_SCK_1 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTF|GPIO_PIN7)
# define GPIO_SPI5_SCK_2 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTH|GPIO_PIN6)
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
# define GPIO_SPI6_MISO (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTG|GPIO_PIN12)
# define GPIO_SPI6_MOSI (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTG|GPIO_PIN14)
# define GPIO_SPI6_NSS (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTG|GPIO_PIN8)
+18 -6
View File
@@ -356,7 +356,8 @@
#define RCC_APB2RSTR_SDIORST (1 << 11) /* Bit 11: SDIO reset */
#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI1 reset */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469) || \
defined(CONFIG_STM32_STM32F411)
# define RCC_APB2RSTR_SPI4RST (1 << 13) /* Bit 13: SPI4 reset */
#endif
#define RCC_APB2RSTR_SYSCFGRST (1 << 14) /* Bit 14: System configuration controller reset */
@@ -364,8 +365,11 @@
#define RCC_APB2RSTR_TIM10RST (1 << 17) /* Bit 17: TIM10 reset */
#define RCC_APB2RSTR_TIM11RST (1 << 18) /* Bit 18: TIM11 reset */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F469) || defined(CONFIG_STM32_STM32F411)
# define RCC_APB2RSTR_SPI5RST (1 << 20) /* Bit 20: SPI 5 reset */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
# define RCC_APB2RSTR_SPI6RST (1 << 21) /* Bit 21: SPI 6 reset */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
@@ -500,7 +504,8 @@
#define RCC_APB2ENR_SDIOEN (1 << 11) /* Bit 11: SDIO clock enable */
#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 clock enable */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469) || \
defined(CONFIG_STM32_STM32F411)
# define RCC_APB2ENR_SPI4EN (1 << 13) /* Bit 13: SPI4 clock enable */
#endif
#define RCC_APB2ENR_SYSCFGEN (1 << 14) /* Bit 14: System configuration controller clock enable */
@@ -508,8 +513,11 @@
#define RCC_APB2ENR_TIM10EN (1 << 17) /* Bit 17: TIM10 clock enable */
#define RCC_APB2ENR_TIM11EN (1 << 18) /* Bit 18: TIM11 clock enable */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F469) || defined(CONFIG_STM32_STM32F411)
# define RCC_APB2ENR_SPI5EN (1 << 20) /* Bit 20: SPI5 clock enable */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
# define RCC_APB2ENR_SPI6EN (1 << 21) /* Bit 21: SPI6 clock enable */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
@@ -649,7 +657,8 @@
#define RCC_APB2LPENR_SDIOLPEN (1 << 11) /* Bit 11: SDIO clock enable during Sleep mode */
#define RCC_APB2LPENR_SPI1LPEN (1 << 12) /* Bit 12: SPI1 clock enable during Sleep mode */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F446) || defined(CONFIG_STM32_STM32F469) || \
defined(CONFIG_STM32_STM32F411)
# define RCC_APB2LPENR_SPI4LPEN (1 << 13) /* Bit 13: SPI4 clock enable during Sleep mode */
#endif
#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14) /* Bit 14: System configuration controller clock enable during Sleep mode */
@@ -657,8 +666,11 @@
#define RCC_APB2LPENR_TIM10LPEN (1 << 17) /* Bit 17: TIM10 clock enable during Sleep mode */
#define RCC_APB2LPENR_TIM11LPEN (1 << 18) /* Bit 18: TIM11 clock enable during Sleep mode */
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
defined(CONFIG_STM32_STM32F469) || defined(CONFIG_STM32_STM32F411)
# define RCC_APB2LPENR_SPI5LPEN (1 << 20) /* Bit 20: SPI5 clock enable during Sleep mode */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
defined(CONFIG_STM32_STM32F469)
# define RCC_APB2LPENR_SPI6LPEN (1 << 21) /* Bit 21: SPI6 clock enable during Sleep mode */
#endif
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) || \
+55 -18
View File
@@ -69,7 +69,7 @@
/* ADC "upper half" support must be enabled */
#ifdef CONFIG_ADC
#ifdef CONFIG_STM32_ADC
/* Some ADC peripheral must be enabled */
@@ -272,6 +272,7 @@
struct stm32_dev_s
{
FAR const struct adc_callback_s *cb;
uint8_t irq; /* Interrupt generated by this ADC block */
uint8_t nchannels; /* Number of channels */
uint8_t cchannels; /* Number of configured channels */
@@ -364,6 +365,8 @@ static int adc123_interrupt(int irq, FAR void *context);
/* ADC Driver Methods */
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void adc_reset(FAR struct adc_dev_s *dev);
static int adc_setup(FAR struct adc_dev_s *dev);
static void adc_shutdown(FAR struct adc_dev_s *dev);
@@ -412,6 +415,7 @@ static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
static const struct adc_ops_s g_adcops =
{
.ao_bind = adc_bind,
#if defined(CONFIG_STM32_STM32L15XX) && \
(STM32_CFGR_PLLSRC != 0 || STM32_SYSCLK_SW != RCC_CFGR_SW_HSI)
.ao_reset = adc_reset_hsi_disable,
@@ -1641,15 +1645,22 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg)
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
int i;
for (i = 0; i < priv->nchannels; i++)
{
adc_receive(dev, priv->current, priv->dmabuffer[priv->current]);
priv->current++;
if (priv->current >= priv->nchannels)
{
/* Restart the conversion sequence from the beginning */
/* Verify that the upper-half driver has bound its callback functions */
priv->current = 0;
if (priv->cb != NULL)
{
DEBUGASSERT(priv->cb->au_receive != NULL);
for (i = 0; i < priv->nchannels; i++)
{
priv->cb->au_receive(dev, priv->current, priv->dmabuffer[priv->current]);
priv->current++;
if (priv->current >= priv->nchannels)
{
/* Restart the conversion sequence from the beginning */
priv->current = 0;
}
}
}
@@ -1660,6 +1671,25 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr, FAR void *arg)
}
#endif
/****************************************************************************
* Name: adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: adc_reset
*
@@ -2702,15 +2732,21 @@ static int adc_interrupt(FAR struct adc_dev_s *dev)
data = adc_getreg(priv, STM32_ADC_DR_OFFSET) & ADC_DR_RDATA_MASK;
/* Give the ADC data to the ADC driver. adc_receive() accepts 3
* parameters:
*
* 1) The first is the ADC device instance for this ADC block.
* 2) The second is the channel number for the data, and
* 3) The third is the converted data for the channel.
*/
/* Verify that the upper-half driver has bound its callback functions */
adc_receive(dev, priv->chanlist[priv->current], data);
if (priv->cb != NULL)
{
/* Give the ADC data to the ADC driver. The ADC receive() method
* accepts 3 parameters:
*
* 1) The first is the ADC device instance for this ADC block.
* 2) The second is the channel number for the data, and
* 3) The third is the converted data for the channel.
*/
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(dev, priv->chanlist[priv->current], data);
}
/* Set the channel number of the next channel that will complete
* conversion.
@@ -2995,6 +3031,7 @@ struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist,
DEBUGASSERT(cchannels <= ADC_MAX_SAMPLES);
priv->cb = NULL;
priv->cchannels = cchannels;
memcpy(priv->chanlist, chanlist, cchannels);
@@ -3009,4 +3046,4 @@ struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist,
#endif /* CONFIG_STM32_ADC1 || CONFIG_STM32_ADC2 ||
* CONFIG_STM32_ADC3 || CONFIG_STM32_ADC4
*/
#endif /* CONFIG_ADC */
#endif /* CONFIG_STM32_ADC */
+16 -21
View File
@@ -125,32 +125,32 @@
struct tiva_adc_step_cfg_s
{
uint8_t adc; /* Parent peripheral */
uint8_t sse; /* Parent sample sequencer (SSE) */
uint8_t step; /* Which step in the sequencer */
uint8_t shold; /* Sample and hold time */
uint8_t flags; /* Last step? Interrupt enabled?
* Internal temperature sensor? */
uint8_t ain; /* Which analog input */
uint8_t adc; /* Parent peripheral */
uint8_t sse; /* Parent sample sequencer (SSE) */
uint8_t step; /* Which step in the sequencer */
uint8_t shold; /* Sample and hold time */
uint8_t flags; /* Last step? Interrupt enabled?
* Internal temperature sensor? */
uint8_t ain; /* Which analog input */
};
/* Sample Sequencer configuration options */
struct tiva_adc_sse_cfg_s
{
uint8_t priority; /* Conversion priority, 0-3 no duplicates */
uint8_t trigger; /* Trigger source */
uint8_t priority; /* Conversion priority, 0-3 no duplicates */
uint8_t trigger; /* Trigger source */
};
/* ADC peripheral configuration options */
struct tiva_adc_cfg_s
{
uint8_t adc; /* ADC peripheral number */
bool sse[4]; /* active SSEs in a bitmask */
struct tiva_adc_sse_cfg_s ssecfg[4]; /* SSE configuration */
uint8_t steps; /* Size of the stepcfg array */
struct tiva_adc_step_cfg_s *stepcfg; /* Step configuration array */
uint8_t adc; /* ADC peripheral number */
bool sse[4]; /* active SSEs in a bitmask */
struct tiva_adc_sse_cfg_s ssecfg[4]; /* SSE configuration */
uint8_t steps; /* Size of the stepcfg array */
struct tiva_adc_step_cfg_s *stepcfg; /* Step configuration array */
};
/****************************************************************************
@@ -165,16 +165,11 @@ extern "C"
#define EXTERN extern
#endif
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Only allow access to upper level ADC drivers if they are enabled */
#ifdef CONFIG_ADC
#ifdef CONFIG_TIVA_ADC
/****************************************************************************
* Driver Function Prototypes
@@ -228,7 +223,7 @@ void tiva_adc_lock(FAR struct tiva_adc_s *priv, int sse);
void tiva_adc_unlock(FAR struct tiva_adc_s *priv, int sse);
#endif /* CONFIG_ADC */
#endif /* CONFIG_TIVA_ADC */
/****************************************************************************
* Library Function Prototypes
+58 -13
View File
@@ -1,8 +1,10 @@
/****************************************************************************
* arch/arm/src/tiva/tiva_adclow.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2015 TRD2 Inc. All rights reserved.
* Author: Calvin Maguranis <calvin.maguranis@trd2inc.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* References:
*
@@ -67,8 +69,8 @@
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
@@ -80,7 +82,7 @@
#include "chip/tiva_pinmap.h"
#include "chip/tiva_syscontrol.h"
#if defined (CONFIG_TIVA_ADC) && defined (CONFIG_ADC)
#ifdef CONFIG_TIVA_ADC
/****************************************************************************
* Pre-processor Definitions
@@ -135,6 +137,8 @@
/* Upper level ADC driver ***************************************************/
static int tiva_adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void tiva_adc_reset(struct adc_dev_s *dev);
static int tiva_adc_setup(struct adc_dev_s *dev);
static void tiva_adc_shutdown(struct adc_dev_s *dev);
@@ -149,6 +153,7 @@ static int tiva_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
static const struct adc_ops_s g_adcops =
{
.ao_bind = tiva_adc_bind,
.ao_reset = tiva_adc_reset,
.ao_setup = tiva_adc_setup,
.ao_shutdown = tiva_adc_shutdown,
@@ -163,6 +168,7 @@ static const struct adc_ops_s g_adcops =
struct tiva_adc_s
{
struct adc_dev_s *dev;
const struct adc_callback_s *cb;
bool cfg; /* Configuration state */
bool ena; /* Operation state */
uint8_t devno; /* ADC device number */
@@ -373,6 +379,25 @@ static void tiva_adc_irqinitialize(struct tiva_adc_cfg_s *cfg)
#endif
}
/****************************************************************************
* Name: tiva_adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int tiva_adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
struct tiva_adc_s *priv = (struct tiva_adc_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: tiva_adc_reset
*
@@ -559,11 +584,20 @@ static int tiva_adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
fifo_count = tiva_adc_sse_data(priv->devno, sse, buf);
for (i = 0; i < fifo_count; ++i)
/* Verify that the upper-half driver has bound its callback functions */
if (priv->cb != NULL)
{
(void)adc_receive(dev,
tiva_adc_get_ain(priv->devno, sse, i),
buf[i]);
DEBUGASSERT(priv->cb->au_receive != NULL);
for (i = 0; i < fifo_count; ++i)
{
/* Perform the data received callback */
priv->cb->au_receive(dev,
tiva_adc_get_ain(priv->devno, sse, i),
buf[i]);
}
}
/* Release our lock on the ADC structure */
@@ -651,18 +685,28 @@ static void tiva_adc_read(void *arg)
/* This is a serious error: indicates invalid pointer indirection
* and should cause a full system stop.
*/
alldbg("PANIC!!! Invalid ADC device number given %d\n", sse->adc);
PANIC();
return;
}
for (i = 0; i < fifo_count; ++i)
/* Verify that the upper-half driver has bound its callback functions */
if (priv->cb != NULL)
{
(void)adc_receive(dev,
tiva_adc_get_ain(sse->adc, sse->num, i),
buf[i]);
avdbg("AIN%d=0x%04x\n",
tiva_adc_get_ain(sse->adc, sse->num, i), buf[i]);
DEBUGASSERT(priv->cb->au_receive != NULL);
for (i = 0; i < fifo_count; ++i)
{
/* Perform the data received callback */
priv->cb->au_receive(dev,
tiva_adc_get_ain(sse->adc, sse->num, i),
buf[i]);
avdbg("AIN%d = 0x%04x\n",
tiva_adc_get_ain(sse->adc, sse->num, i), buf[i]);
}
}
/* Exit, re-enabling ADC interrupts */
@@ -858,6 +902,7 @@ int tiva_adc_initialize(const char *devpath, struct tiva_adc_cfg_s *cfg,
/* Now we are initialized */
adc->ena = true;
adc->cb = NULL;
#ifdef CONFIG_DEBUG_ANALOG
tiva_adc_runtimeobj_vals();
@@ -1041,4 +1086,4 @@ static void tiva_adc_dump_dev(void)
}
#endif
#endif /* CONFIG_TIVA_ADC && CONFIG_ADC */
#endif /* CONFIG_TIVA_ADC */
+11
View File
@@ -11,6 +11,16 @@ config ADC
not only Analog-to-Digital Converters (ADC) but also amplifiers and
analog multiplexers.
This selection enables:
- The upper half, device-independent ADC character driver, and
- Selection of common lower half ADC drivers.
MCU-specific, lower half drivers may be selected independently of
CONFIG_ADC. However, if CONFIG_ADC is selected, then it is assume
that lower half ADC drivers will be used only with the commoun ADC
upper half driver.
if ADC
config ADC_FIFOSIZE
@@ -46,6 +56,7 @@ config ADC_ADS125X
bool "TI ADS1255/ADS1256 support"
default n
select SPI
select SCHED_HPWORK
if ADC_ADS125X
+92 -16
View File
@@ -1,9 +1,10 @@
/************************************************************************************
* arch/drivers/analog/ad5410.c
*
* Copyright (C) 2010, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-05 initial version
* Gregory Nutt <gnutt@nuttx.org>
*
* This file is a part of NuttX:
*
@@ -85,6 +86,9 @@ struct up_dev_s
* ad_private Function Prototypes
****************************************************************************/
static void dac_lock(FAR struct spi_dev_s *spi);
static void dac_unlock(FAR struct spi_dev_s *spi);
/* DAC methods */
static void dac_reset(FAR struct dac_dev_s *dev);
@@ -121,64 +125,136 @@ static struct dac_dev_s g_dacdev =
* ad_private Functions
****************************************************************************/
/* Reset the DAC device. Called early to initialize the hardware. This
* is called, before ao_setup() and on error conditions.
*/
/****************************************************************************
* Name: dac_lock
*
* Description:
* Lock and configure the SPI bus.
*
****************************************************************************/
static void dac_lock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, true);
SPI_SETMODE(spi, SPIDEV_MODE0);
SPI_SETBITS(spi, 8);
(void)SPI_HWFEATURES(spi, 0);
SPI_SETFREQUENCY(spi, 400000);
}
/****************************************************************************
* Name: dac_unlock
*
* Description:
* Unlock the SPI bus.
*
****************************************************************************/
static void dac_unlock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, false);
}
/****************************************************************************
* Name: dac_reset
*
* Description:
* Reset the DAC device. Called early to initialize the hardware. This
* is called, before ao_setup() and on error conditions.
*
****************************************************************************/
static void dac_reset(FAR struct dac_dev_s *dev)
{
}
/* Configure the DAC. This method is called the first time that the DAC
* device is opened. This will occur when the port is first opened.
* This setup includes configuring and attaching DAC interrupts. Interrupts
* are all disabled upon return.
*/
/****************************************************************************
* Name: dac_setup
*
* Description:
* Configure the DAC. This method is called the first time that the DAC
* device is opened. This will occur when the port is first opened.
* This setup includes configuring and attaching DAC interrupts. Interrupts
* are all disabled upon return.
*
****************************************************************************/
static int dac_setup(FAR struct dac_dev_s *dev)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi = priv->spi;
dac_lock(spi);
SPI_SELECT(spi, priv->devno, true);
SPI_SEND(spi, AD5410_REG_CMD);
SPI_SEND(spi, (AD5410_CMD_OUTEN | AD5410_CMD_420MA) >> 8);
SPI_SEND(spi, AD5410_CMD_OUTEN | AD5410_CMD_420MA);
SPI_SELECT(spi, priv->devno, false);
dac_unlock(spi);
return OK;
}
/* Disable the DAC. This method is called when the DAC device is closed.
* This method reverses the operation the setup method.
*/
/****************************************************************************
* Name: dac_shutdown
*
* Description:
* Disable the DAC. This method is called when the DAC device is closed.
* This method reverses the operation the setup method.
*
****************************************************************************/
static void dac_shutdown(FAR struct dac_dev_s *dev)
{
}
/* Call to enable or disable TX interrupts */
/****************************************************************************
* Name: dac_txint
*
* Description:
* Call to enable or disable TX interrupts
*
****************************************************************************/
static void dac_txint(FAR struct dac_dev_s *dev, bool enable)
{
}
static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
/****************************************************************************
* Name: dac_send
*
* Description:
*
****************************************************************************/
static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi = priv->spi;
dac_lock(spi);
SPI_SELECT(spi, priv->devno, true);
SPI_SEND(spi, AD5410_REG_WR);
SPI_SEND(spi, (uint8_t)(msg->am_data >> 24));
SPI_SEND(spi, (uint8_t)(msg->am_data >> 16));
SPI_SELECT(spi, priv->devno, false);
dac_unlock(spi);
dac_txdone(&g_dacdev);
return 0;
}
/* All ioctl calls will be routed through this method */
/****************************************************************************
* Name: dac_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg)
static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg)
{
dbg("Fix me:Not Implemented\n");
return 0;
+42 -8
View File
@@ -1,9 +1,10 @@
/****************************************************************************
* drivers/analog/adc.c
*
* Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-04 initial version
* Gregory Nutt <gnutt@nuttx.org>
*
* Derived from drivers/can.c
*
@@ -70,12 +71,14 @@ static int adc_close(FAR struct file *filep);
static ssize_t adc_read(FAR struct file *fielp, FAR char *buffer,
size_t buflen);
static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch,
int32_t data);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations adc_fops =
static const struct file_operations g_adc_fops =
{
adc_open, /* open */
adc_close, /* close */
@@ -88,6 +91,11 @@ static const struct file_operations adc_fops =
#endif
};
static const struct adc_callback_s g_adc_callback =
{
adc_receive /* au_receive */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -361,15 +369,11 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: adc_receive
****************************************************************************/
int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
{
FAR struct adc_fifo_s *fifo = &dev->ad_recv;
int nexttail;
@@ -408,12 +412,30 @@ int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
return err;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: adc_register
****************************************************************************/
int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
{
int ret;
DEBUGASSERT(path != NULL && dev != NULL);
/* Bind the upper-half callbacks to the lower half ADC driver */
DEBUGASSERT(dev->ad_ops != NULL && dev->ad_ops->ao_bind != NULL);
ret = dev->ad_ops->ao_bind(dev, &g_adc_callback);
if (ret < 0)
{
adbg("ERROR: Failed to bind callbacks: %d\n", ret);
return ret;
}
/* Initialize the ADC device structure */
dev->ad_ocount = 0;
@@ -421,7 +443,19 @@ int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
sem_init(&dev->ad_recv.af_sem, 0, 0);
sem_init(&dev->ad_closesem, 0, 1);
/* Reset the ADC hardware */
DEBUGASSERT(dev->ad_ops->ao_reset != NULL);
dev->ad_ops->ao_reset(dev);
return register_driver(path, &adc_fops, 0444, dev);
/* Register the ADC character driver */
ret = register_driver(path, &g_adc_fops, 0444, dev);
if (ret < 0)
{
sem_destroy(&dev->ad_recv.af_sem);
sem_destroy(&dev->ad_closesem);
}
return ret;
}
+62 -18
View File
@@ -2,8 +2,10 @@
* drivers/sensors/ads1242.c
* Character driver for the MCP3426 Differential Input 16 Bit Delta/Sigma ADC
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2015 DS-Automotion GmbH. All rights reserved.
* Author: Alexander Entinger <a.entinger@ds-automotion.com>
* Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -70,6 +72,8 @@ struct ads1242_dev_s
/* SPI Helpers */
static void ads1242_lock(FAR struct spi_dev_s *spi);
static void ads1242_unlock(FAR struct spi_dev_s *spi);
static void ads1242_reset(FAR struct ads1242_dev_s *dev);
static void ads1242_performSelfGainCalibration(
FAR struct ads1242_dev_s *dev);
@@ -128,19 +132,50 @@ static const struct file_operations g_ads1242_fops =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ads1242_lock
*
* Description:
* Lock and configure the SPI bus.
*
****************************************************************************/
static void ads1242_lock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, true);
SPI_SETMODE(spi, ADS1242_SPI_MODE);
SPI_SETBITS(spi, 8);
(void)SPI_HWFEATURES(spi, 0);
SPI_SETFREQUENCY(spi, ADS1242_SPI_FREQUENCY);
}
/****************************************************************************
* Name: ads1242_unlock
*
* Description:
* Unlock the SPI bus.
*
****************************************************************************/
static void ads1242_unlock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, false);
}
/****************************************************************************
* Name: ads1242_reset
****************************************************************************/
static void ads1242_reset(FAR struct ads1242_dev_s *dev)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true); /* Set nADC_SPI_CS to low which selects the ADS1242 */
SPI_SEND(dev->spi, ADS1242_CMD_RESET);/* Issue reset command */
SPI_SELECT(dev->spi, 0, false); /* Set nADC_SPI_CS to high which deselects the ADS1242 */
up_mdelay(100); /* Wait a little so the device has time to perform a proper reset */
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -149,11 +184,13 @@ static void ads1242_reset(FAR struct ads1242_dev_s *dev)
static void ads1242_performSelfGainCalibration(FAR struct ads1242_dev_s *dev)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_SELF_GAIN_CALIB);
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -162,11 +199,13 @@ static void ads1242_performSelfGainCalibration(FAR struct ads1242_dev_s *dev)
static void ads1242_performSelfOffsetCalibration(FAR struct ads1242_dev_s *dev)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_SELF_OFFSET_CALIB);
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -176,11 +215,13 @@ static void ads1242_performSelfOffsetCalibration(FAR struct ads1242_dev_s *dev)
static void
ads1242_performSystemOffsetCalibration(FAR struct ads1242_dev_s *dev)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_SYSTEM_OFFSET_CALIB);
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -190,8 +231,9 @@ ads1242_performSystemOffsetCalibration(FAR struct ads1242_dev_s *dev)
static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev,
FAR uint32_t *conversion_result)
{
SPI_SELECT(dev->spi, 0, true);
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_READ_DATA);
/* Delay between last SCLK edge for DIN and first SCLK edge for DOUT:
@@ -212,6 +254,8 @@ static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev,
*conversion_result |= ((uint32_t)(SPI_SEND(dev->spi, 0xFF))) << 0;
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -227,11 +271,15 @@ static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev,
static void ads1242_write_reg(FAR struct ads1242_dev_s *dev,
uint8_t const reg_addr, uint8_t const reg_value)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_WRITE_REGISTER | reg_addr);
SPI_SEND(dev->spi, 0x00); /* Write 1 Byte */
SPI_SEND(dev->spi, reg_value);
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -248,6 +296,8 @@ static void ads1242_write_reg(FAR struct ads1242_dev_s *dev,
static void ads1242_read_reg(FAR struct ads1242_dev_s *dev,
uint8_t const reg_addr, FAR uint8_t *reg_value)
{
ads1242_lock(dev->spi);
SPI_SELECT(dev->spi, 0, true);
SPI_SEND(dev->spi, ADS1242_CMD_READ_REGISTER | reg_addr);
SPI_SEND(dev->spi, 0x00); /* Read 1 Byte */
@@ -261,6 +311,8 @@ static void ads1242_read_reg(FAR struct ads1242_dev_s *dev,
*reg_value = SPI_SEND(dev->spi, 0xFF);
SPI_SELECT(dev->spi, 0, false);
ads1242_unlock(dev->spi);
}
/****************************************************************************
@@ -562,14 +614,6 @@ int ads1242_register(FAR const char *devpath, FAR struct spi_dev_s *spi,
kmm_free(priv);
}
/* setup SPI frequency */
SPI_SETFREQUENCY(spi, ADS1242_SPI_FREQUENCY);
/* Setup SPI mode */
SPI_SETMODE(spi, ADS1242_SPI_MODE);
return ret;
}
+217 -43
View File
@@ -1,10 +1,10 @@
/************************************************************************************
* arch/drivers/analog/ads1255.c
*
* Copyright (C) 2010, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-05 initial version
* 0.2 2011-08-25 fix bug in g_adcdev (cd_ops -> ad_ops,cd_priv -> ad_priv)
* Gregory Nutt <gnutt@nuttx.org>
*
* This file is a part of NuttX:
*
@@ -39,6 +39,10 @@
*
************************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
@@ -47,15 +51,20 @@
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/spi/spi.h>
#include <nuttx/analog/adc.h>
#if defined(CONFIG_ADC_ADS1255)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ADS125X_BUFON 0x02
#define ADS125X_BUFOFF 0x00
@@ -102,11 +111,14 @@
#endif
/****************************************************************************
* ad_private Types
* Private Types
****************************************************************************/
struct up_dev_s
struct ads1255_dev_s
{
FAR const struct adc_callback_s *cb;
FAR struct spi_dev_s *spi; /* Cached SPI device reference */
struct work_s work;
uint8_t channel;
uint32_t sps;
uint8_t pga;
@@ -114,36 +126,45 @@ struct up_dev_s
const uint8_t *mux;
int irq;
int devno;
FAR struct spi_dev_s *spi; /* Cached SPI device reference */
};
/****************************************************************************
* ad_private Function Prototypes
* Private Function Prototypes
****************************************************************************/
static void adc_lock(FAR struct spi_dev_s *spi);
static void adc_unlock(FAR struct spi_dev_s *spi);
/* ADC methods */
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
static void adc_reset(FAR struct adc_dev_s *dev);
static int adc_setup(FAR struct adc_dev_s *dev);
static void adc_shutdown(FAR struct adc_dev_s *dev);
static void adc_rxint(FAR struct adc_dev_s *dev, bool enable);
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg);
/* Interrupt handling */
static void adc_worker(FAR void *arg);
static int adc_interrupt(int irq, void *context);
/****************************************************************************
* ad_private Data
* Private Data
****************************************************************************/
static const struct adc_ops_s g_adcops =
{
.ao_reset = adc_reset, /* ao_reset */
.ao_setup = adc_setup, /* ao_setup */
.ao_bind = adc_bind, /* ao_bind */
.ao_reset = adc_reset, /* ao_reset */
.ao_setup = adc_setup, /* ao_setup */
.ao_shutdown = adc_shutdown, /* ao_shutdown */
.ao_rxint = adc_rxint, /* ao_rxint */
.ao_ioctl = adc_ioctl /* ao_read */
.ao_rxint = adc_rxint, /* ao_rxint */
.ao_ioctl = adc_ioctl /* ao_read */
};
static struct up_dev_s g_adcpriv =
static struct ads1255_dev_s g_adcpriv =
{
.mux = (const uint8_t [])
{
@@ -190,43 +211,112 @@ static uint8_t getspsreg(uint16_t sps)
}
/****************************************************************************
* ad_private Functions
* Private Functions
****************************************************************************/
/* Reset the ADC device. Called early to initialize the hardware. This
* is called, before ao_setup() and on error conditions.
*/
static void adc_reset(FAR struct adc_dev_s *dev)
/****************************************************************************
* Name: adc_lock
*
* Description:
* Lock and configure the SPI bus.
*
****************************************************************************/
static void adc_lock(FAR struct spi_dev_s *spi)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi = priv->spi;
(void)SPI_LOCK(spi, true);
SPI_SETMODE(spi, SPIDEV_MODE1);
SPI_SETBITS(spi, 8);
(void)SPI_HWFEATURES(spi, 0);
SPI_SETFREQUENCY(spi, CONFIG_ADS1255_FREQUENCY);
}
/****************************************************************************
* Name: adc_unlock
*
* Description:
* Unlock the SPI bus.
*
****************************************************************************/
static void adc_unlock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, false);
}
/****************************************************************************
* Name: adc_bind
*
* Description:
* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*
****************************************************************************/
static int adc_bind(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback)
{
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
priv->cb = callback;
return OK;
}
/****************************************************************************
* Name: adc_reset
*
* Description:
* Reset the ADC device. Called early to initialize the hardware. This
* is called, before ao_setup() and on error conditions.
*
****************************************************************************/
static void adc_reset(FAR struct adc_dev_s *dev)
{
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi;
DEBUGASSERT(priv != NULL && priv->spi != NULL);
spi = priv->spi;
adc_lock(spi);
usleep(1000);
SPI_SELECT(spi, priv->devno, true);
SPI_SEND(spi, ADS125X_WREG + 0x03); /* WRITE SPS REG */
SPI_SEND(spi, 0x00); /* count=1 */
SPI_SEND(spi, 0x63);
SPI_SELECT(spi, priv->devno, false);
adc_unlock(spi);
}
/* Configure the ADC. This method is called the first time that the ADC
* device is opened. This will occur when the port is first opened.
* This setup includes configuring and attaching ADC interrupts. Interrupts
* are all disabled upon return.
*/
/****************************************************************************
* Name: adc_setup
*
* Description:
* Configure the ADC. This method is called the first time that the ADC
* device is opened. This will occur when the port is first opened.
* This setup includes configuring and attaching ADC interrupts. Interrupts
* are all disabled upon return.
*
****************************************************************************/
static int adc_setup(FAR struct adc_dev_s *dev)
static int adc_setup(FAR struct adc_dev_s *dev)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi = priv->spi;
int ret = irq_attach(priv->irq, adc_interrupt);
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
FAR struct spi_dev_s *spi;
int ret;
DEBUGASSERT(priv != NULL && priv->spi != NULL);
spi = priv->spi;
ret = irq_attach(priv->irq, adc_interrupt);
if (ret == OK)
{
adc_lock(spi);
SPI_SELECT(spi, priv->devno, true);
SPI_SEND(spi, ADS125X_WREG); /* WRITE REG from 0 */
SPI_SEND(spi, 0x03); /* count=4+1 */
@@ -245,28 +335,47 @@ static int adc_setup(FAR struct adc_dev_s *dev)
usleep(1000);
SPI_SEND(spi, ADS125X_SELFCAL);
SPI_SELECT(spi, priv->devno, false);
adc_unlock(spi);
up_enable_irq(priv->irq);
}
return ret;
}
/* Disable the ADC. This method is called when the ADC device is closed.
* This method reverses the operation the setup method.
*/
/****************************************************************************
* Name: adc_shutdown
*
* Description:
* Disable the ADC. This method is called when the ADC device is closed.
* This method reverses the operation the setup method.
*
****************************************************************************/
static void adc_shutdown(FAR struct adc_dev_s *dev)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
up_disable_irq(priv->irq);
irq_detach(priv->irq);
}
/* Call to enable or disable RX interrupts */
/****************************************************************************
* Name: adc_rxint
*
* Description:
* Call to enable or disable RX interrupts
*
****************************************************************************/
static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
if (enable)
{
up_enable_irq(priv->irq);
@@ -277,21 +386,44 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
}
}
/* All ioctl calls will be routed through this method */
/****************************************************************************
* Name: adc_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
{
dbg("Fix me:Not Implemented\n");
return 0;
}
static int adc_interrupt(int irq, void *context)
/****************************************************************************
* Name: adc_worker
*
* Description:
* ADC interrupt work
*
****************************************************************************/
static void adc_worker(FAR void *arg)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
FAR struct spi_dev_s *spi = priv->spi;
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)arg;
FAR struct spi_dev_s *spi;
unsigned char buf[4];
unsigned char ch;
DEBUGASSERT(priv != NULL && priv->spi != NULL);
spi = priv->spi;
/* REVISIT: Cannot perform SPI operations from an interrupt handler!
* Need to use the high priority work queue.
*/
adc_lock(spi);
SPI_SELECT(spi, priv->devno, true);
SPI_SEND(spi, ADS125X_RDATA);
up_udelay(10);
@@ -316,7 +448,46 @@ static int adc_interrupt(int irq, void *context)
SPI_SEND(spi, ADS125X_WAKEUP);
SPI_SELECT(spi, priv->devno, false);
adc_receive(&g_adcdev, priv->channel, *(int32_t *)buf);
adc_unlock(spi);
/* Verify that the upper-half driver has bound its callback functions */
if (priv->cb != NULL)
{
/* Perform the data received callback */
DEBUGASSERT(priv->cb->au_receive != NULL);
priv->cb->au_receive(&g_adcdev, priv->channel, *(int32_t *)buf);
}
/* Re-enable ADC interrupts */
up_enable_irq(priv->irq);
}
/****************************************************************************
* Name: adc_interrupt
*
* Description:
* ADC interrupt handler
*
****************************************************************************/
static int adc_interrupt(int irq, void *context)
{
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv;
DEBUGASSERT(priv != NULL);
/* Disable further ADC interrupts until the worker thread has executed. */
up_disable_irq(priv->irq);
/* Schedule the ADC work for the worker thread. Whent he sample has been
* processed, the ADC interrupt will be re-enabled.
*/
DEBUGVERIFY(work_queue(HPWORK, &priv->work, adc_worker, priv, 0));
return OK;
}
@@ -341,10 +512,13 @@ static int adc_interrupt(int irq, void *context)
FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi,
unsigned int devno)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv;
DEBUGASSERT(spi != NULL);
/* Driver state data */
priv->cb = NULL;
priv->spi = spi;
priv->devno = devno;
return &g_adcdev;
+7 -4
View File
@@ -65,15 +65,18 @@ static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
static const struct file_operations devnull_fops =
{
0, /* open */
0, /* close */
NULL, /* open */
NULL, /* close */
devnull_read, /* read */
devnull_write, /* write */
0, /* seek */
0 /* ioctl */
NULL, /* seek */
NULL /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, devnull_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
/****************************************************************************
+7 -4
View File
@@ -65,15 +65,18 @@ static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
static const struct file_operations devzero_fops =
{
0, /* open */
0, /* close */
NULL, /* open */
NULL, /* close */
devzero_read, /* read */
devzero_write, /* write */
0, /* seek */
0 /* ioctl */
NULL, /* seek */
NULL /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, devzero_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
/****************************************************************************
+14 -21
View File
@@ -33,11 +33,9 @@
#
############################################################################
# Don't build anything if there is no NX support for LCD drivers
ifeq ($(CONFIG_NX_LCDDRIVER),y)
# Include Graphics LCD drivers
# Include support for Graphics LCD drivers
ifeq ($(CONFIG_LCD_P14201),y)
CSRCS += p14201.c
@@ -102,30 +100,25 @@ endif
ifeq ($(CONFIG_LCD_RA8875),y)
CSRCS += ra8875.c
endif
endif # CONFIG_NX_LCDDRIVER
# Include Alphanumeric/Segment LCD drivers too
ifeq ($(CONFIG_SLCD),y)
# Include support for Alphanumeric/Segment LCD drivers
ifeq ($(CONFIG_LCD_BACKPACK),y)
CSRCS += pcf8574_lcd_backpack.c
endif
endif # CONFIG_SLCD
# Include LCD driver build support
DEPPATH += --dep-path lcd
VPATH += :lcd
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)lcd}
# Include LCD driver build support (the nested if-then-else implements an OR)
ifeq ($(CONFIG_NX_LCDDRIVER),y)
DEPPATH += --dep-path lcd
VPATH += :lcd
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)lcd}
else ifeq ($(CONFIG_SLCD),y)
# Include Alphanumeric/Segment LCD drivers only
ifeq ($(CONFIG_LCD_BACKPACK),y)
CSRCS += pcf8574_lcd_backpack.c
endif
# Include LCD driver build support
DEPPATH += --dep-path lcd
VPATH += :lcd
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)lcd}
DEPPATH += --dep-path lcd
VPATH += :lcd
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)lcd}
endif
+241 -22
View File
@@ -63,9 +63,9 @@
/* timing characteristics of the LCD interface */
#define DELAY_US_NYBBLE0 200
#define DELAY_US_NYBBLE1 100
#define DELAY_US_WRITE 35
#define DELAY_US_NYBBLE0 20
#define DELAY_US_NYBBLE1 10
#define DELAY_US_WRITE 40
#define DELAY_US_HOMECLEAR 1500
/* HD44780 commands */
@@ -86,6 +86,8 @@
# define lcdvdbg(x...)
#endif
#define MAX_OPENCNT (255) /* Limit of uint8_t */
/****************************************************************************
* Private Types
****************************************************************************/
@@ -95,6 +97,8 @@ struct pcf8574_lcd_dev_s
FAR struct i2c_master_s *i2c; /* I2C interface */
struct pcf8574_lcd_backpack_config_s cfg; /* gpio configuration */
uint8_t bl_bit; /* current backlight bit */
uint8_t refs; /* Number of references */
uint8_t unlinked; /* We are unlinked, so teardown on last close */
sem_t sem_excl; /* mutex */
};
@@ -117,12 +121,16 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t pcf8574_lcd_write(FAR struct file *filep,
FAR const char *buffer, size_t buflen);
static off_t pcf8574_lcd_seek(FAR struct file *filep, off_t offset, int whence);
static int pcf8574_lcd_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
#ifndef CONFIG_DISABLE_POLL
static int pcf8574lcd_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int pcf8574_lcd_unlink(FAR struct inode *inode);
#endif
/****************************************************************************
* Private Data
@@ -134,12 +142,14 @@ static const struct file_operations g_pcf8574_lcd_fops =
pcf8574_lcd_close, /* close */
pcf8574_lcd_read, /* read */
pcf8574_lcd_write, /* write */
0, /* seek */
pcf8574_lcd_seek, /* seek */
pcf8574_lcd_ioctl, /* ioctl */
#ifndef CONFIG_DISABLE_POLL
pcf8574lcd_poll, /* poll */
#endif
0 /* unlink */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
pcf8574_lcd_unlink /* unlink */
#endif
};
/****************************************************************************
@@ -259,7 +269,7 @@ static inline uint8_t rc2addr(FAR struct pcf8574_lcd_dev_s *priv,
* of first line, and fourth line is a continuation of second.
*/
return (row - 2) * 0x40 + (col - priv->cfg.cols);
return (row - 2) * 0x40 + (col + priv->cfg.cols);
}
}
@@ -383,9 +393,14 @@ static void latch_nybble(FAR struct pcf8574_lcd_dev_s *priv, uint8_t nybble,
en_bit = 1 << priv->cfg.en;
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
/* Put the nybble, preserving backlight, reset R/~W and set EN and maybe RS */
/* Put the nybble, preserving backlight, reset R/~W and maybe RS */
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | en_bit | rs_bit;
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | rs_bit;
pca8574_write(priv, lcddata);
/* Now set EN */
lcddata |= en_bit;
pca8574_write(priv, lcddata);
up_udelay(DELAY_US_NYBBLE0); /* setup */
@@ -419,9 +434,14 @@ static uint8_t load_nybble(FAR struct pcf8574_lcd_dev_s *priv, bool rs)
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
rw_bit = 1 << priv->cfg.rw;
/* Put highs on the data lines, preserve, set R/~W and set EN and maybe RS */
/* Put highs on the data lines, preserve, set R/~W and maybe RS */
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | en_bit | rw_bit | rs_bit;
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | rw_bit | rs_bit;
pca8574_write(priv, lcddata);
/* Now set EN */
lcddata |= en_bit;
pca8574_write(priv, lcddata);
up_udelay(DELAY_US_NYBBLE0); /* setup */
@@ -538,7 +558,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
{
/* Wait for more than 15 ms after Vcc for the LCD to stabilize */
usleep(20000);
usleep(50000);
/* Perform the init sequence. This sequence of commands is constructed so
* that it will get the device into nybble mode irrespective of what state
@@ -548,7 +568,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
* the remainder of operations.
*/
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms*/
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms */
latch_nybble(priv, 0x30>>4, false);
usleep(5000);
@@ -556,15 +576,17 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
/* Send Command 0x30, set 8-bit mode, and wait > 100 us */
latch_nybble(priv, 0x30>>4, false);
usleep(200);
usleep(5000);
/* Send Command 0x30, set 8-bit mode */
latch_nybble(priv, 0x30>>4, false);
usleep(200);
/* now Function set: Set interface to be 4 bits long (only 1 cycle write for the first time). */
latch_nybble(priv, 0x20>>4, false);
usleep(5000);
/* Function set: DL=0;Interface is 4 bits, N=1 (2 Lines), F=0 (5x8 dots font) */
@@ -988,6 +1010,53 @@ static int lcd_getstream(FAR struct lib_instream_s *instream)
return EOF;
}
/****************************************************************************
* Name: lcd_fpos_to_curpos
*
* Description:
* Convert a file logical offset to a screen cursor pos (row,col). This
* discounts 'synthesized' line feeds at the end of screen lines.
*
****************************************************************************/
static void lcd_fpos_to_curpos(FAR struct pcf8574_lcd_dev_s *priv,
off_t fpos, uint8_t *row, uint8_t *col, bool* onlf)
{
int virtcols;
virtcols = (priv->cfg.cols + 1);
/* Determine if this is a 'virtual' position (on the synthetic LF) */
*onlf = (priv->cfg.cols == fpos % virtcols);
/* Adjust off any preceding synthetic LF's to get linear position */
fpos -= fpos / virtcols;
/* Compute row/col from linear position */
*row = fpos / priv->cfg.cols;
*col = fpos % priv->cfg.cols;
}
/****************************************************************************
* Name: lcd_curpos_to_fpos
*
* Description:
* Convert a screen cursor pos (row,col) to a file logical offset. This
* includes 'synthesized' line feeds at the end of screen lines.
*
****************************************************************************/
static void lcd_curpos_to_fpos(FAR struct pcf8574_lcd_dev_s *priv,
uint8_t row, uint8_t col, off_t* fpos)
{
/* the logical file position is the linear position plus any synthetic LF */
*fpos = (row * priv->cfg.cols) + col + row;
}
/****************************************************************************
* Name: pcf8574_lcd_open
*
@@ -998,6 +1067,22 @@ static int lcd_getstream(FAR struct lib_instream_s *instream)
static int pcf8574_lcd_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
/* Increment the reference count */
sem_wait(&priv->sem_excl);
if (priv->refs == MAX_OPENCNT)
{
return -EMFILE;
}
else
{
priv->refs++;
}
sem_post(&priv->sem_excl);
return OK;
}
@@ -1011,7 +1096,35 @@ static int pcf8574_lcd_open(FAR struct file *filep)
static int pcf8574_lcd_close(FAR struct file *filep)
{
return OK;
FAR struct inode *inode = filep->f_inode;
FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
int ret;
/* Decrement the reference count */
sem_wait(&priv->sem_excl);
if (priv->refs == 0)
{
ret = -EIO;
}
else
{
priv->refs--;
/* If we had previously unlinked, but there were open references at the
* time, we need to do the final teardown now.
*/
if (priv->refs == 0 && priv->unlinked)
{
/* We have no real teardown at present */
}
ret = OK;
}
sem_post(&priv->sem_excl);
return ret;
}
/****************************************************************************
@@ -1019,7 +1132,8 @@ static int pcf8574_lcd_close(FAR struct file *filep)
*
* Description:
* This simply reads as much of the display memory as possible. This is
* probably not very interesting.
* generally not very interesting, but we do it in a way that allows us to
* 'cat' the LCD contents via the shell.
*
****************************************************************************/
@@ -1032,22 +1146,44 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
uint8_t addr;
uint8_t row;
uint8_t col;
bool onlf;
sem_wait(&priv->sem_excl);
/* Get current cursor position so we can restore it */
(void)lcd_read_busy_addr(priv, &addr);
addr2rc(priv, addr, &row, &col);
/* Just read the entire display into the given buffer, as much as possible */
/* Convert file position to row/col address and position DDADDR there */
lcd_fpos_to_curpos(priv, filep->f_pos, &row, &col, &onlf);
lcd_set_curpos(priv, row, col);
/* Read as much of the display as possible */
nIdx = 0;
row = 0;
col = 0;
while (nIdx < buflen && row < priv->cfg.rows)
{
/* Synthesize end-of-line LF and advance to start of next row */
if (onlf)
{
/* Synthesize LF for all but last row */
if ( row < priv->cfg.rows-1)
{
buffer[nIdx] = '\x0a';
onlf = false;
++filep->f_pos;
++nIdx;
}
++row;
col = 0;
continue;
}
/* If we are at start of line we will need to update DDRAM address */
if (0 == col)
{
lcd_set_curpos(priv, row, 0);
@@ -1055,12 +1191,15 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
buffer[nIdx] = lcd_getdata(priv);
++filep->f_pos;
++nIdx;
++col;
/* If we are now at the end of a line, we setup for the synthetic LF */
if (priv->cfg.cols == col)
{
++row;
col = 0;
onlf = true;
}
}
@@ -1214,10 +1353,62 @@ static ssize_t pcf8574_lcd_write(FAR struct file *filep,
}
}
/* Wherever we wound up, update our logical file pos to reflect it */
lcd_curpos_to_fpos(priv, row, col, &filep->f_pos);
sem_post(&priv->sem_excl);
return buflen;
}
/****************************************************************************
* Name: pcf8574_lcd_seek
*
* Description:
* Seek the logical file pointer to the specified position. This is
* probably not very interesting except possibly for (SEEK_SET, 0) to
* rewind the pointer for a subsequent read().
* The file pointer is logical, and includes synthesized LF chars at the
* end of the display lines.
*
****************************************************************************/
static off_t pcf8574_lcd_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
int maxpos;
sem_wait(&priv->sem_excl);
maxpos = priv->cfg.rows * priv->cfg.cols + (priv->cfg.rows - 1);
switch (whence)
{
case SEEK_CUR:
filep->f_pos += offset;
if (filep->f_pos > maxpos)
filep->f_pos = maxpos;
break;
case SEEK_SET:
filep->f_pos = offset;
if (filep->f_pos > maxpos)
filep->f_pos = maxpos;
break;
case SEEK_END:
filep->f_pos = maxpos;
break;
default:
/* Return EINVAL if the whence argument is invalid */
filep->f_pos = -EINVAL;
}
sem_post(&priv->sem_excl);
return filep->f_pos;
}
/****************************************************************************
* Name: pcf8574_lcd_ioctl
*
@@ -1337,6 +1528,32 @@ static int pcf8574lcd_poll(FAR struct file *filep, FAR struct pollfd *fds,
}
#endif
/****************************************************************************
* Name: pcf8574_lcd_unlink
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int pcf8574_lcd_unlink(FAR struct inode *inode)
{
FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
int ret = OK;
sem_wait(&priv->sem_excl);
priv->unlinked = true;
/* If there are no open references to the driver then tear it down now */
if (priv->refs == 0)
{
/* We have no real teardown at present */
ret = OK;
}
sem_post(&priv->sem_excl);
return ret;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -1383,6 +1600,8 @@ int pcf8574_lcd_backpack_register(FAR const char *devpath,
priv->i2c = i2c;
priv->cfg = *cfg;
priv->bl_bit = priv->cfg.bl_active_high ? 0 : (1 << priv->cfg.bl);
priv->refs = 0;
priv->unlinked = false;
sem_init(&priv->sem_excl, 0, 1);
/* Initialize */
+14 -7
View File
@@ -225,7 +225,7 @@ Example of programming a character image:
Now character '\x04' will display as an 'up arrow'.
Note, you might consider avoiding the use of code point 0x00 unless
absolutely needed, because the embedded nul character can cause
you absolutely need it, because the embedded nul character can cause
problems. The driver, and write() apis are binary, and unaffected,
but things like printf() and puts() assume C-style strings, and are
affected.
@@ -237,9 +237,16 @@ Troubleshooting
bus timeouts that suggest a non-responsive slave.
* Check your board wiring and configuration specification. Buzz
out the lines if you have to.
* Con't forget to check the 'contrast' potentiometer. The voltage
at the central wiper should be approximately 0.29 V. The useful
range of voltages at this pin is very narrow, and outside that
range there will be nothing visible on the display, so most of the
turn range of the pot is non-useful. Much of human life has been
wasted in the rediscovery of this farcically idiotic
* Remember to set the (ros,cols) geometry in pcf8574_lcd_backpack_config_s
before registration of the driver, since this cannot be determined
programmatically.
* If the driver registration step seems to 'hang' it could be the I2C
driver performing retries due to no response from the LCD backpack. Check
the address. Turning on debug output for I2C can help make this visible.
* Don't forget to check the 'contrast' potentiometer. The voltage at the
central wiper should be approximately 0.3 V - 2.4 V, but the actual value
is is dependent on the physics of the attached LCD module. The useful
range of voltages at this pin for any given LCD is quite narrow, and
outside that range there will be nothing visible on the display, so most
of the turn range of the pot is non-useful. It's less 'contrast' and
more 'LCD segment drive bias'.
+7 -4
View File
@@ -140,12 +140,15 @@ static const struct file_operations userled_fops =
{
userled_open, /* open */
userled_close, /* close */
0, /* read */
NULL, /* read */
userled_write, /* write */
0, /* seek */
NULL, /* seek */
userled_ioctl /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, 0 /* poll */
, NULL /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
@@ -441,7 +444,7 @@ static int userled_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* Check that a valid LED is being set */
if (led < 8 * sizeof(userled_set_t) &&
if ((size_t)led < 8 * sizeof(userled_set_t) &&
(priv->lu_supported & (1 << led)) != 0)
{
/* Update the LED state */
+9 -6
View File
@@ -107,16 +107,19 @@ static int loop_geometry(FAR struct inode *inode,
static const struct block_operations g_bops =
{
loop_open, /* open */
loop_close, /* close */
loop_read, /* read */
loop_open, /* open */
loop_close, /* close */
loop_read, /* read */
#ifdef CONFIG_FS_WRITABLE
loop_write, /* write */
loop_write, /* write */
#else
NULL, /* write */
NULL, /* write */
#endif
loop_geometry, /* geometry */
NULL /* ioctl */
NULL /* ioctl */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
/****************************************************************************
+35 -32
View File
@@ -92,7 +92,7 @@ static void pipecommon_semtake(sem_t *sem);
* Name: pipecommon_semtake
****************************************************************************/
static void pipecommon_semtake(sem_t *sem)
static void pipecommon_semtake(FAR sem_t *sem)
{
while (sem_wait(sem) != 0)
{
@@ -109,7 +109,8 @@ static void pipecommon_semtake(sem_t *sem)
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, pollevent_t eventset)
static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev,
pollevent_t eventset)
{
int i;
@@ -120,7 +121,7 @@ static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, pollevent_t events
for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++)
{
struct pollfd *fds = dev->d_fds[i];
FAR struct pollfd *fds = dev->d_fds[i];
if (fds)
{
fds->revents |= eventset & (fds->events | POLLERR | POLLHUP);
@@ -158,7 +159,7 @@ FAR struct pipe_dev_s *pipecommon_allocdev(void)
/* Allocate a private structure to manage the pipe */
dev = (struct pipe_dev_s *)kmm_malloc(sizeof(struct pipe_dev_s));
dev = (FAR struct pipe_dev_s *)kmm_malloc(sizeof(struct pipe_dev_s));
if (dev)
{
/* Initialize the private structure */
@@ -190,10 +191,10 @@ void pipecommon_freedev(FAR struct pipe_dev_s *dev)
int pipecommon_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int sval;
int ret;
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int sval;
int ret;
DEBUGASSERT(dev != NULL);
@@ -302,9 +303,9 @@ int pipecommon_open(FAR struct file *filep)
int pipecommon_close(FAR struct file *filep)
{
struct inode *inode = filep->f_inode;
struct pipe_dev_s *dev = inode->i_private;
int sval;
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int sval;
DEBUGASSERT(dev && dev->d_refs > 0);
@@ -408,14 +409,14 @@ int pipecommon_close(FAR struct file *filep)
ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
struct inode *inode = filep->f_inode;
struct pipe_dev_s *dev = inode->i_private;
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
#ifdef CONFIG_DEV_PIPEDUMP
FAR uint8_t *start = (FAR uint8_t *)buffer;
FAR uint8_t *start = (FAR uint8_t *)buffer;
#endif
ssize_t nread = 0;
int sval;
int ret;
ssize_t nread = 0;
int sval;
int ret;
DEBUGASSERT(dev);
@@ -467,7 +468,7 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
/* Then return whatever is available in the pipe (which is at least one byte) */
nread = 0;
while (nread < len && dev->d_wrndx != dev->d_rdndx)
while ((size_t)nread < len && dev->d_wrndx != dev->d_rdndx)
{
*buffer++ = dev->d_buffer[dev->d_rdndx];
if (++dev->d_rdndx >= CONFIG_DEV_PIPE_SIZE)
@@ -497,14 +498,15 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
* Name: pipecommon_write
****************************************************************************/
ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t len)
ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
{
struct inode *inode = filep->f_inode;
struct pipe_dev_s *dev = inode->i_private;
ssize_t nwritten = 0;
ssize_t last;
int nxtwrndx;
int sval;
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
ssize_t nwritten = 0;
ssize_t last;
int nxtwrndx;
int sval;
DEBUGASSERT(dev);
pipe_dumpbuffer("To PIPE:", (FAR uint8_t *)buffer, len);
@@ -559,7 +561,8 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t
/* Is the write complete? */
if (++nwritten >= len)
nwritten++;
if ((size_t)nwritten >= len)
{
/* Yes.. Notify all of the waiting readers that more data is available */
@@ -717,7 +720,7 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds,
{
/* This is a request to tear down the poll. */
struct pollfd **slot = (struct pollfd **)fds->priv;
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
#ifdef CONFIG_DEBUG
if (!slot)
@@ -745,9 +748,9 @@ errout:
int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct inode *inode = filep->f_inode;
struct pipe_dev_s *dev = inode->i_private;
int ret = -EINVAL;
FAR struct inode *inode = filep->f_inode;
FAR struct pipe_dev_s *dev = inode->i_private;
int ret = -EINVAL;
#ifdef CONFIG_DEBUG
/* Some sanity checking */
@@ -792,7 +795,7 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
count = dev->d_wrndx - dev->d_rdndx;
}
*(int *)arg = count;
*(FAR int *)arg = count;
ret = 0;
}
break;
@@ -812,7 +815,7 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
count = ((CONFIG_DEV_PIPE_SIZE - dev->d_wrndx) + dev->d_rdndx) - 1;
}
*(int *)arg = count;
*(FAR int *)arg = count;
ret = 0;
}
break;
+36
View File
@@ -83,6 +83,9 @@ struct max31855_dev_s
* Private Function Prototypes
****************************************************************************/
static void max31855_lock(FAR struct spi_dev_s *spi);
static void max31855_unlock(FAR struct spi_dev_s *spi);
/* Character driver methods */
static int max31855_open(FAR struct file *filep);
@@ -112,6 +115,37 @@ static const struct file_operations g_max31855fops =
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: max31855_lock
*
* Description:
* Lock and configure the SPI bus.
*
****************************************************************************/
static void max31855_lock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, true);
SPI_SETMODE(spi, SPIDEV_MODE0);
SPI_SETBITS(spi, 8);
(void)SPI_HWFEATURES(spi, 0);
SPI_SETFREQUENCY(spi, 400000);
}
/****************************************************************************
* Name: max31855_unlock
*
* Description:
* Unlock the SPI bus.
*
****************************************************************************/
static void max31855_unlock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, false);
}
/****************************************************************************
* Name: max31855_open
*
@@ -167,6 +201,7 @@ static ssize_t max31855_read(FAR struct file *filep, FAR char *buffer, size_t bu
/* Enable MAX31855's chip select */
max31855_lock(priv->spi);
SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, true);
/* Read temperature */
@@ -176,6 +211,7 @@ static ssize_t max31855_read(FAR struct file *filep, FAR char *buffer, size_t bu
/* Disable MAX31855's chip select */
SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, false);
max31855_unlock(priv->spi);
regval = (regmsb & 0xFF000000) >> 24;
regval |= (regmsb & 0xFF0000) >> 8;
+36
View File
@@ -80,6 +80,9 @@ struct max6675_dev_s
* Private Function Prototypes
****************************************************************************/
static void max6675_lock(FAR struct spi_dev_s *spi)
static void max6675_unlock(FAR struct spi_dev_s *spi)
/* Character driver methods */
static int max6675_open(FAR struct file *filep);
@@ -108,6 +111,37 @@ static const struct file_operations g_max6675fops =
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: max6675_lock
*
* Description:
* Lock and configure the SPI bus.
*
****************************************************************************/
static void max6675_lock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, true);
SPI_SETMODE(spi, SPIDEV_MODE0);
SPI_SETBITS(spi, 8);
(void)SPI_HWFEATURES(spi, 0);
SPI_SETFREQUENCY(spi, 400000);
}
/****************************************************************************
* Name: max6675_unlock
*
* Description:
* Unlock the SPI bus.
*
****************************************************************************/
static void max6675_unlock(FAR struct spi_dev_s *spi)
{
(void)SPI_LOCK(spi, false);
}
/****************************************************************************
* Name: max6675_open
*
@@ -163,6 +197,7 @@ static ssize_t max6675_read(FAR struct file *filep, FAR char *buffer, size_t buf
/* Enable MAX6675's chip select */
max6675_lock(priv->spi);
SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, true);
/* Read temperature */
@@ -172,6 +207,7 @@ static ssize_t max6675_read(FAR struct file *filep, FAR char *buffer, size_t buf
/* Disable MAX6675's chip select */
SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, false);
max6675_unlock(priv->spi);
regval = (regmsb & 0xFF00) >> 8;
regval |= (regmsb & 0xFF) << 8;
+127 -40
View File
@@ -139,7 +139,7 @@ struct ms58xx_dev_s
****************************************************************************/
/* CRC Calculation */
static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcIndex);
static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcndx, uint16_t crcmask);
/* I2C Helpers */
@@ -200,7 +200,7 @@ static const struct file_operations g_fops =
*
****************************************************************************/
static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcIndex)
static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcndx, uint16_t crcmask)
{
uint16_t cnt;
uint16_t n_rem;
@@ -208,8 +208,8 @@ static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcIndex)
uint8_t n_bit;
n_rem = 0x00;
crc_read = src[crcIndex];
src[crcIndex] = (0xff00 & (src[7]));
crc_read = src[crcndx];
src[crcndx] &= ~crcmask;
for (cnt = 0; cnt < 16; cnt++)
{
@@ -236,7 +236,7 @@ static uint8_t ms58xx_crc(FAR uint16_t *src, uint8_t crcIndex)
}
n_rem = (0x000F & (n_rem >> 12));
src[crcIndex] = crc_read;
src[crcndx] = crc_read;
return (n_rem ^ 0x00);
}
@@ -369,24 +369,73 @@ static int ms58xx_readadc(FAR struct ms58xx_dev_s *priv, FAR uint32_t *adc)
*adc = (uint32_t)buffer[0] << 16 |
(uint32_t)buffer[1] << 8 |
(uint32_t)buffer[2];
sndbg("adc: %06x ret: %d\n", *adc, ret);
return ret;
}
/****************************************************************************
* Name: ms58xx_setosr
* Name: ms58xx_setosr_1
*
* Description:
* Set the oversampling ratio.
*
****************************************************************************/
static int ms58xx_setosr(FAR struct ms58xx_dev_s *priv, uint16_t osr)
static int ms58xx_setosr_1(FAR struct ms58xx_dev_s *priv, uint16_t osr)
{
int ret = OK;
switch (osr)
{
case 256:
priv->delay = 600;
priv->osr = 0x0;
break;
sndbg("osr: %04x\n", osr);
case 512:
priv->delay = 1170;
priv->osr = 0x2;
break;
case 1024:
priv->delay = 2280;
priv->osr = 0x4;
break;
case 2048:
priv->delay = 4540;
priv->osr = 0x6;
break;
case 4096:
priv->delay = 9040;
priv->osr = 0x8;
break;
case 8192:
priv->delay = 18080;
priv->osr = 0xA;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/****************************************************************************
* Name: ms58xx_setosr_2
*
* Description:
* Set the oversampling ratio.
*
****************************************************************************/
static int ms58xx_setosr_2(FAR struct ms58xx_dev_s *priv, uint16_t osr)
{
int ret = OK;
switch (osr)
{
case 256:
@@ -409,26 +458,6 @@ static int ms58xx_setosr(FAR struct ms58xx_dev_s *priv, uint16_t osr)
priv->delay = 9040;
break;
case 8192:
switch (priv->model)
{
case MS58XX_MODEL_MS5805_02:
case MS58XX_MODEL_MS5837_30:
priv->delay = 18080;
break;
case MS58XX_MODEL_MS5803_02:
case MS58XX_MODEL_MS5803_05:
case MS58XX_MODEL_MS5803_07:
case MS58XX_MODEL_MS5803_14:
case MS58XX_MODEL_MS5803_30:
case MS58XX_MODEL_MS5806_02:
default:
ret = -EINVAL;
break;
}
break;
default:
ret = -EINVAL;
break;
@@ -442,6 +471,44 @@ static int ms58xx_setosr(FAR struct ms58xx_dev_s *priv, uint16_t osr)
return ret;
}
/****************************************************************************
* Name: ms58xx_setosr
*
* Description:
* Set the oversampling ratio.
*
****************************************************************************/
static int ms58xx_setosr(FAR struct ms58xx_dev_s *priv, uint16_t osr)
{
int ret = OK;
sndbg("osr: %04x\n", osr);
switch (priv->model)
{
case MS58XX_MODEL_MS5805_02:
case MS58XX_MODEL_MS5837_30:
ret = ms58xx_setosr_1(priv,osr);
break;
case MS58XX_MODEL_MS5803_02:
case MS58XX_MODEL_MS5803_05:
case MS58XX_MODEL_MS5803_07:
case MS58XX_MODEL_MS5803_14:
case MS58XX_MODEL_MS5803_30:
case MS58XX_MODEL_MS5806_02:
ret = ms58xx_setosr_2(priv,osr);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
/****************************************************************************
* Name: ms58xx_readprom
*
@@ -499,7 +566,7 @@ static int ms58xx_readprom(FAR struct ms58xx_dev_s *priv)
crcmask = (uint16_t)0xf << crcshift;
crc = (uint8_t)((prom[crcindex] & crcmask) >> crcshift);
if (crc != ms58xx_crc(prom, crcindex))
if (crc != ms58xx_crc(prom, crcindex, crcmask))
{
sndbg("crc mismatch\n");
return -ENODEV;
@@ -787,7 +854,27 @@ static int ms58xx_close(FAR struct file *filep)
static ssize_t ms58xx_read(FAR struct file *filep, FAR char *buffer,
size_t buflen)
{
return 0;
ssize_t size;
FAR struct inode *inode = filep->f_inode;
FAR struct ms58xx_dev_s *priv = inode->i_private;
FAR struct ms58xx_measure_s *p = (FAR struct ms58xx_measure_s *)buffer;
size = buflen;
while (size >= sizeof(*p))
{
if (ms58xx_measure(priv) < 0)
{
return -1;
}
p->temperature = priv->temp;
p->pressure = priv->press;
p++;
size -= sizeof(*p);
}
return size;
}
/****************************************************************************
@@ -907,16 +994,16 @@ int ms58xx_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
/* Sanity check */
DEBUGASSERT(i2c != NULL);
DEBUGASSERT((model == MS58XX_MODEL_MS5803_02 ||
model == MS58XX_MODEL_MS5803_05 ||
model == MS58XX_MODEL_MS5803_07 ||
model == MS58XX_MODEL_MS5803_14 ||
model == MS58XX_MODEL_MS5803_30 ||
model == MS58XX_MODEL_MS5806_02) &&
(addr == MS58XX_ADDR0 || addr == MS58XX_ADDR1) ||
(model == MS58XX_MODEL_MS5805_02 ||
model == MS58XX_MODEL_MS5837_30) &&
addr == MS58XX_ADDR0);
DEBUGASSERT(((model == MS58XX_MODEL_MS5803_02 ||
model == MS58XX_MODEL_MS5803_05 ||
model == MS58XX_MODEL_MS5803_07 ||
model == MS58XX_MODEL_MS5803_14 ||
model == MS58XX_MODEL_MS5803_30 ||
model == MS58XX_MODEL_MS5806_02) &&
(addr == MS58XX_ADDR0 || addr == MS58XX_ADDR1)) ||
((model == MS58XX_MODEL_MS5805_02 ||
model == MS58XX_MODEL_MS5837_30) &&
addr == MS58XX_ADDR0));
/* Initialize the device's structure */
+7 -4
View File
@@ -70,14 +70,17 @@ static int lowconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
static const struct file_operations g_consoleops =
{
0, /* open */
0, /* close */
NULL, /* open */
NULL, /* close */
lowconsole_read, /* read */
lowconsole_write, /* write */
0, /* seek */
NULL, /* seek */
lowconsole_ioctl /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, 0 /* poll */
, NULL /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
+5 -2
View File
@@ -103,6 +103,9 @@ static const struct file_operations g_serialops =
#ifndef CONFIG_DISABLE_POLL
, uart_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
/************************************************************************************
@@ -487,7 +490,7 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer,
* interrupted transfer.
*/
if (buflen < nwritten)
if (buflen < (size_t)nwritten)
{
/* Some data was transferred. Return the number of bytes that
* were successfully transferred.
@@ -557,7 +560,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
* data from the end of the buffer.
*/
while (recvd < buflen)
while ((size_t)recvd < buflen)
{
#ifdef CONFIG_SERIAL_REMOVABLE
/* If the removable device is no longer connected, refuse to read any
+14 -11
View File
@@ -123,14 +123,17 @@ static int ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds,
static const struct file_operations g_ramlogfops =
{
0, /* open */
0, /* close */
ramlog_read, /* read */
ramlog_write, /* write */
0, /* seek */
0 /* ioctl */
NULL, /* open */
NULL, /* close */
ramlog_read, /* read */
ramlog_write, /* write */
NULL, /* seek */
NULL /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, ramlog_poll /* poll */
, ramlog_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
@@ -206,7 +209,7 @@ static void ramlog_pollnotify(FAR struct ramlog_dev_s *priv,
static int ramlog_addchar(FAR struct ramlog_dev_s *priv, char ch)
{
irqstate_t flags;
int nexthead;
size_t nexthead;
/* Disable interrupts (in case we are NOT called from interrupt handler) */
@@ -271,7 +274,7 @@ static ssize_t ramlog_read(FAR struct file *filep, FAR char *buffer, size_t len)
/* Loop until something is read */
for (nread = 0; nread < len; )
for (nread = 0; (size_t)nread < len; )
{
/* Get the next byte from the buffer */
@@ -437,7 +440,7 @@ static ssize_t ramlog_write(FAR struct file *filep, FAR const char *buffer, size
* interrupts.
*/
for (nwritten = 0; nwritten < len; nwritten++)
for (nwritten = 0; (size_t)nwritten < len; nwritten++)
{
/* Get the next character to output */
@@ -529,7 +532,7 @@ int ramlog_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
FAR struct inode *inode = filep->f_inode;
FAR struct ramlog_dev_s *priv;
pollevent_t eventset;
int ndx;
size_t ndx;
int ret;
int i;
+5 -2
View File
@@ -114,10 +114,13 @@ static const struct file_operations g_timerops =
timer_close, /* close */
timer_read, /* read */
timer_write, /* write */
0, /* seek */
NULL, /* seek */
timer_ioctl /* ioctl */
#ifndef CONFIG_DISABLE_POLL
, 0 /* poll */
, NULL /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif
};
+46 -29
View File
@@ -1,10 +1,10 @@
/************************************************************************************
* include/nuttx/analog/adc.h
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
* History: 0.1 2011-08-04 initial version
* 0.2 remove ao_read
* Gregory Nutt <gnutt@nuttx.org>
*
* Derived from include/nuttx/can.h
*
@@ -75,6 +75,27 @@
/************************************************************************************
* Public Types
************************************************************************************/
/* These are callbacks to notify the upper-half driver of ADC events */
struct adc_dev_s;
struct adc_callback_s
{
/* This method is called from the lower half, platform-specific ADC logic when
* new ADC sample data is available.
*
* Input Parameters:
* dev - The ADC device structure that was previously registered by adc_register()
* ch - And ID for the ADC channel number that generated the data
* data - The actual converted data from the channel.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*/
CODE int (*au_receive)(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
};
/* This describes on ADC message */
struct adc_msg_s
{
@@ -82,6 +103,8 @@ struct adc_msg_s
int32_t am_data; /* ADC convert result (4 bytes) */
} packed_struct;
/* This describes a FIFO of ADC messages */
struct adc_fifo_s
{
sem_t af_sem; /* Counting semaphore */
@@ -99,6 +122,13 @@ struct adc_fifo_s
struct adc_dev_s;
struct adc_ops_s
{
/* Bind the upper-half driver callbacks to the lower-half implementation. This
* must be called early in order to receive ADC event notifications.
*/
CODE int (*ao_bind)(FAR struct adc_dev_s *dev,
FAR const struct adc_callback_s *callback);
/* Reset the ADC device. Called early to initialize the hardware. This
* is called, before ao_setup() and on error conditions.
*/
@@ -129,8 +159,8 @@ struct adc_ops_s
};
/* This is the device structure used by the driver. The caller of
* adc_register() must allocate and initialize this structure. The
* calling logic need only set all fields to zero except:
* adc_register() must allocate and initialize this structure. The calling
* logic need only set all fields to zero except:
*
* The elements of 'ad_ops', and 'ad_priv'
*
@@ -139,21 +169,24 @@ struct adc_ops_s
struct adc_dev_s
{
#ifdef CONFIG_ADC
/* Fields managed by common upper half ADC logic */
uint8_t ad_ocount; /* The number of times the device has been opened */
uint8_t ad_nrxwaiters; /* Number of threads waiting to enqueue a message */
sem_t ad_closesem; /* Locks out new opens while close is in progress */
sem_t ad_recvsem; /* Used to wakeup user waiting for space in ad_recv.buffer */
struct adc_fifo_s ad_recv; /* Describes receive FIFO */
#endif
/* Fields provided by lower half ADC logic */
FAR const struct adc_ops_s *ad_ops; /* Arch-specific operations */
FAR void *ad_priv; /* Used by the arch-specific logic */
};
/************************************************************************************
* Public Data
************************************************************************************/
/************************************************************************************
* Public Functions
* Public Function Prototypes
************************************************************************************/
#if defined(__cplusplus)
@@ -164,6 +197,7 @@ extern "C"
/************************************************************************************
* "Upper-Half" ADC Driver Interfaces
************************************************************************************/
/************************************************************************************
* Name: adc_register
*
@@ -188,28 +222,10 @@ extern "C"
int adc_register(FAR const char *path, FAR struct adc_dev_s *dev);
/************************************************************************************
* Name: adc_receive
*
* Description:
* This function is called from the lower half, platform-specific ADC logic when
* new ADC sample data is available.
*
* Input Parameters:
* dev - The ADC device structure that was previously registered by adc_register()
* ch - And ID for the ADC channel number that generated the data
* data - The actualy converted data from the channel.
*
* Returned Value:
* Zero on success; a negated errno value on failure.
*
************************************************************************************/
int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
/************************************************************************************
* Platform-Independent "Lower Half" ADC Driver Interfaces
************************************************************************************/
/************************************************************************************
* Name: up_ads1255initialize
*
@@ -218,7 +234,8 @@ int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
*
************************************************************************************/
FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi, unsigned int devno);
FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi,
unsigned int devno);
#if defined(__cplusplus)
}
+3 -3
View File
@@ -155,10 +155,10 @@ struct i2c_master_s;
struct i2c_msg_s;
struct i2c_ops_s
{
int (*transfer)(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s *msgs,
int count);
CODE int (*transfer)(FAR struct i2c_master_s *dev,
FAR struct i2c_msg_s *msgs, int count);
#ifdef CONFIG_I2C_RESET
int (*reset)(FAR struct i2c_master_s *dev);
CODE int (*reset)(FAR struct i2c_master_s *dev);
#endif
};

Some files were not shown because too many files have changed in this diff Show More