mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
Merged nuttx/nuttx into master
This commit is contained in:
@@ -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/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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---
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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---
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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---
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) || \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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'.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user