mirror of
https://github.com/apache/nuttx.git
synced 2026-08-10 06:55:13 +00:00
Merged patacongo/nuttx into master
This commit is contained in:
commit
b66405df31
1532 changed files with 70287 additions and 21010 deletions
811
ChangeLog
811
ChangeLog
|
|
@ -1233,7 +1233,7 @@
|
|||
macros definitions (patch submitted by Tiago Maluta).
|
||||
* Documents/NuttxPortingGuide.html, configs/README.txt, etc. -
|
||||
Replaced CONFIG_EXAMPLE with CONFIG_APP_DIR (see documents for
|
||||
desciption). This allows NuttX application code to be built
|
||||
description). This allows NuttX application code to be built
|
||||
outside of the examples/ directory.
|
||||
|
||||
For people who have their own configurations and/or Makefiles,
|
||||
|
|
@ -1325,7 +1325,7 @@
|
|||
* configs/avr32dev1/nsh: Added a configuration to support the NuttShell
|
||||
(NSH). As of this writing, here is a problem receiving serial data (this
|
||||
is, very likely, my hardware setup).
|
||||
* lib/lib_open.c: Fix an error in fdopen when a valid file desciptor does
|
||||
* lib/lib_open.c: Fix an error in fdopen when a valid file descriptor does
|
||||
not refer to an open file.
|
||||
* configs/olimex-lpc1766stk: Add support for the Olimex LPC1766-STK
|
||||
development board. The OS test and NSH configurations (only) have been
|
||||
|
|
@ -1654,7 +1654,7 @@
|
|||
* arch/*/include/*/type.h: On some compilers, char defaults as unsigned.
|
||||
Explicitly add signed to integer types if signed is what is required.
|
||||
* arch/*: For all architectures -- Global register state save structure
|
||||
(usually called current_regs) should be marked volatile; Added general
|
||||
(usually called g_current_regs) should be marked volatile; Added general
|
||||
capability to support nested interrupts (not fully realized for all
|
||||
architectures).
|
||||
* sched/task_create.c: Add support for starting kernel-mode thread.
|
||||
|
|
@ -2741,7 +2741,7 @@
|
|||
the worker thread, disabling interrupts does not provide protected; Need to
|
||||
disable pre-emption. (2) Fix handling of touch ID and (2) add some logic to
|
||||
prevent certain kinds of data overrun.
|
||||
* include/nx/nxtk.h and graphics/nx/nxtk/nxtk_internal.h: Move setting
|
||||
* include/nx/nxtk.h and graphics/nx/nxtk/nxtk.h: Move setting
|
||||
of configuration defaults from the internal header file to a place where
|
||||
other logic can use the defaults.
|
||||
* graphics/nxtk/nxtk_events.c: Fixed an important but in the logic that
|
||||
|
|
@ -4114,7 +4114,7 @@
|
|||
group exits.
|
||||
* sched/waitpid.c, task_exithook.c and include/nuttx/sched.h:
|
||||
Move waitpid data data structures to task group. Callers of
|
||||
of waitpid() are now only awakened whent he final thread of the
|
||||
of waitpid() are now only awakened when the final thread of the
|
||||
task group exits.
|
||||
* sched/mq_descreate.c, mq_open.c, mq_remove.c, group_leave.c, and
|
||||
include/nuttx/sched.h: Move list of opened message queues to
|
||||
|
|
@ -4533,7 +4533,7 @@
|
|||
* arch/arm/src/lpc17_lcd.c: Rommel Marcelo got the LPC1788
|
||||
framebuffer-based LCD working. Very nice! (2013-4-08).
|
||||
* arch/arm/src/lm/lm_clockconfig.c and configs/lm4f120-launchpad:
|
||||
Fix handling of the RCC SYSDIV2 field whent the PLL output is
|
||||
Fix handling of the RCC SYSDIV2 field when the PLL output is
|
||||
400MHz. Don't forget to set the USERCC2 bit in the register or
|
||||
all is for naught (2013-4-09).
|
||||
* configs/zkit-arm-1769/src/up_lcd.c, up_ssp.c, and up_spi.c:
|
||||
|
|
@ -4680,7 +4680,7 @@
|
|||
* arch/arm/src/kl/kl_gpio.c and .h, configs/freedom-kl25z/src/freedom-kl25z.h,
|
||||
and configs/freedom-kl25z/src/kl_led.c: Fixes LEDs on the Freedom KL25Z
|
||||
board (2013-5-6).
|
||||
* arch/arm/src/kinetis/kinetis_pin.c and arch/arm/src/kinetis/kinetis_internal.h:
|
||||
* arch/arm/src/kinetis/kinetis_pin.c and arch/arm/src/kinetis/kinetis.h:
|
||||
The Kinetis GPIO logic had some of the same issues as did the
|
||||
Kinetis L (2013-5-6).
|
||||
* arch/arm/src/stm32/stm32_idle.c: Add an option to conditionally disable
|
||||
|
|
@ -5333,7 +5333,7 @@
|
|||
* arch/arm/src/sama5/sam_memories.c and .h: Centralize logic for
|
||||
conversions between physical and virtual addresses (2013-8-9).
|
||||
* arch/arm/src/sama5/sam_hsmci.c and sam34/sam_hsmci.c: Correct a
|
||||
race condition in the SAMA5 HSCMI driver: The tranfer done
|
||||
race condition in the SAMA5 HSCMI driver: The transfer done
|
||||
interrupt was firing before the wait was started. Fix this and
|
||||
also backported the changes to SAM3/4 (untested). Now HSCMI is
|
||||
functional on the SAMA5 with DMA! (2013-8-10).
|
||||
|
|
@ -9175,7 +9175,7 @@
|
|||
build framework and skeleton files for Tiva I2C driver. Initial
|
||||
commit is just the STM32 I2C driver with name changes and STM32-
|
||||
specific logic removed (2014-12-9).
|
||||
* fs/procfs/fs_procfs.c: Add procfs write support. From Ken Petit
|
||||
* fs/procfs/fs_procfs.c: Add procfs write support. From Ken Pettit
|
||||
(2014-12-9).
|
||||
* include/crc8.h, libc/misc/lib_crc8.c, and Make.defs: Add CRC8 support.
|
||||
From Ken Pettit (2014-12-9).
|
||||
|
|
@ -10045,7 +10045,7 @@
|
|||
stm32_rtcc.c, stm32_rtcounter.c, and stm32f*_rcc.c: The
|
||||
STM32F4Discovery board doesn't come with a Low speed external
|
||||
oscillator so the default LSE source for the RTC doesn't work. In
|
||||
stm32_rtcc.c the up_rtcinitialize() logic doesn't work with the LSI.
|
||||
stm32_rtcc.c the up_rtc_initialize() logic doesn't work with the LSI.
|
||||
The check on RTC_MAGIC on the BK0R register lead to rtc_setup() call
|
||||
that rightfully enables the lsi clock; but the next times, when the
|
||||
rtc is already setup, the rtc_resume() call does NOT start the lsi
|
||||
|
|
@ -10383,7 +10383,7 @@
|
|||
corrected implementation of pthread_kill() will direct the signal
|
||||
specifically to the specific pthread and no other (2015-05-13).
|
||||
* arch/arm/include/samdl, arch/arm/src/samdl, configs/samd20-xplained:
|
||||
Rename the samd/ directories and configuratino varialbes to samdl to
|
||||
Rename the samd/ directories and configuration varialbes to samdl to
|
||||
all the same directory structure to support the SAML21 (2015-05-14).
|
||||
* arch/arm/include/samdl and arch/arm/src/samdl: And chip definitions,
|
||||
configuration framework, and placeholder memory map and pin
|
||||
|
|
@ -10559,7 +10559,7 @@
|
|||
* arch/arm/src/sama5/sam_can.c: Fix SAMA5 CAN frame construction. From
|
||||
Max Holtzberg (2015-06-07).
|
||||
|
||||
7.11 2015-xx-xx Gregory Nutt <gnutt@nuttx.org>
|
||||
7.11 2015-08-13 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* arch/arm/src/efm32/efm32_spi.c: Correct write to incorrect register in
|
||||
EFM32 SPI driver. From Pierre-noel Bouteville (2015-06-09).
|
||||
|
|
@ -10600,7 +10600,7 @@
|
|||
* arch/arm/include/samdl and arch/arm/src/samdl: Add architecture support
|
||||
for the SAMD21 family (2015-06-19).
|
||||
* configs/samd21-xplained: Board configuration for the SAMD21 Xplained
|
||||
bord (2015-06-21).
|
||||
board (2015-06-21).
|
||||
* arch/arm/src/sam34/sam_lowputc.c: Back out an error introduced with
|
||||
commit 02c33f66c5a8be774034cd40e4125e9323c7b4d8. Causes an infinite
|
||||
loop in up_lowputc(). From Max Neklyudov (2015-06-22).
|
||||
|
|
@ -10618,8 +10618,8 @@
|
|||
* SAM3/4: Add a TWI driver for the SAM4CM. From Max Neklyudov
|
||||
(2015-06-22).
|
||||
* SAMV7 Xplained: In clock configuration, divider was set to 25 to get
|
||||
25*12MHz=300MHz CPU clock. The correct multiplier is 24 becaue the
|
||||
calculatin if (24+1)*12MHz. So the board was running at 312MHz.
|
||||
25*12MHz=300MHz CPU clock. The correct multiplier is 24 because the
|
||||
calculation if (24+1)*12MHz. So the board was running at 312MHz.
|
||||
From Efim Monjak (2015-06-26).
|
||||
* NFS client: Fix prototype of unbind method. The function prototype
|
||||
was not updated for NFS after a recent change to the file system
|
||||
|
|
@ -10729,7 +10729,7 @@
|
|||
for the STMicro STM32 F7 (2015-07-15).
|
||||
* drivers/can.c: Fix an issue in the CAN driver where the rx_sem
|
||||
count can grow beyond bounds (2015-07-15).
|
||||
* configs/stm32f762g-disco/: Add initialize support for the STMicor
|
||||
* configs/stm32f762g-disco/: Add initialize support for the STMicro
|
||||
STM32 F7 Discovery board. This is a work in progress and will be a
|
||||
while before it is fully functional (2015-07-16).
|
||||
* arch/../up_etherstub.c, arch/../up_initialize, and other files: Add
|
||||
|
|
@ -10787,17 +10787,784 @@
|
|||
* arch/arm/src/samv7: Add an MCAN driver for the SAMV7 platform
|
||||
(2015-08-06).
|
||||
* drivers/sensors/lm92.c and include/nuttx/sensors/lm92.h: Add a driver
|
||||
for the LM92 temperature sensor. Contributed by Paul Patience
|
||||
for the LM92 temperature sensor. Contributed by Paul Alexander Patience
|
||||
(2015-08-06).
|
||||
* drivers/sensors/as5048b.c and include/nuttx/sensors/as5048b.h: Add
|
||||
support for an AS5048B rotary magnetic sensor. From Paul Patience
|
||||
(2015-08-06).
|
||||
support for an AS5048B rotary magnetic sensor. From Paul Alexander
|
||||
Patience (2015-08-07).
|
||||
* include/nuttx/spi/slave.h: Add a definition of an SPI slave
|
||||
interface (2015-08-08).
|
||||
* arch/arm/src/samv7: Add the framework for an SPI slave drvier. This
|
||||
* arch/arm/src/samv7: Add the framework for an SPI slave driver. This
|
||||
driver has a lot of missing logic on initial commit (2015-08-09).
|
||||
* arch/arm/src/samv7: Basic, no-DMA SPI slave driver is in place
|
||||
(2015-080=-10).
|
||||
(2015-08-10).
|
||||
* fs/vfs/epoll.c and include/sys/epoll.h: Add a very simple epoll layer
|
||||
just around poll calls. To satisfy build app requirements. From Anton
|
||||
D. Kachalov.
|
||||
D. Kachalov (2015-08-10).
|
||||
* drivers/mtd/ramtron.c: Update to include supportf for newer
|
||||
RAMTRON parts. From David Sidrane (2015-08-10).
|
||||
* Networking: Allow receipt of empty UDP packets. From Max Neklyudov
|
||||
(2015-08-11).
|
||||
* drivers/sensors/mb7040.c and include/nuttx/sensors/mb7040.h: Add
|
||||
support for a MB7040 sonar driver. From Paul Alexander Patience
|
||||
(2015-08-11).
|
||||
* net/udp: Add support for send() for connected UDP sockets
|
||||
(2015-08-11).
|
||||
* drivers/sensors/ms5805.c and include/nuttx/sensors/ms5805.h: Add
|
||||
support for an MS5805 altimeter. From Paul Alexander Patience
|
||||
(2015-08-12).
|
||||
|
||||
7.12 2015-10-01 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* fs/vfs/fs_poll.c: Use sem_tickwait() instead of sem_timedwait()
|
||||
From Macs Neklyudov (2015-08-13).
|
||||
* fs/vfs/fs_poll.c: If we fail to setup the poll for any file
|
||||
descriptor, for any reason, set the POLLERR bit (2015-08-13).
|
||||
* libc/stdlib: Add support for div() to the C library. From
|
||||
OrbitalFox (2015-08-14).
|
||||
* libc/stdlib: Might as well add ldiv() and lldiv() to since
|
||||
these are equivalent to div() with long and long long types,
|
||||
respectively, instead of int (2015-08-14).
|
||||
* include/signal.h and files that include it: Add si_errno to
|
||||
siginfo_t (2015-08-14).
|
||||
* drivers/sensors/mx58xx.c and include/nuttx/sensors/ms58xx.h:
|
||||
Generalize the MS5805 altimeter driver to support other family
|
||||
members and rename to ms58xx. From Paul Alexander Patience
|
||||
(2015-08-14).
|
||||
* Network drivers. Fix bug in tun interface driver. From Max
|
||||
Neklyudov (2015-08-17).
|
||||
* STM32: Added definitions for STM32F303K6, STM32F303K8, STM32F303C6,
|
||||
STM32F303C8, STM32F303RD, and STM32F303RE devices. From Paul
|
||||
Alexander Patience (2015-08-17).
|
||||
* include/nuttx/can.h and all CAN drivers: Add an error indication
|
||||
bit to the CAN message report. This indication must then be cleared
|
||||
in all existing drivers. More to come (2015-08-18).
|
||||
* arch/arm/src/lpc17/lpc17_irq.c: Set NVIC vector address so that
|
||||
code can execute with a bootloader or can execute from RAM. From
|
||||
Pavel Pisa (2015-08-20).
|
||||
* All ARMV7-M IRQ setup: Always set the NVIC vector table address
|
||||
unconditionally. This is needed in cases where the code is running
|
||||
with a bootload and when the code is running from RAM. It is also
|
||||
needed by the logic of up_ramvec_initialize() which gets the vector
|
||||
base address from the NVIC. Suggested by Pavel Pisa (2015-08-21).
|
||||
* SAMV7 USBHS DCD: The device controller driver is (finally) functional
|
||||
(2015-08-21).
|
||||
* recvfrom(): Correct wait for new data when NET_UDP_READAHEAD is
|
||||
enabled. Fix size accounting when recvfrom_udpreadahead() sets
|
||||
state.rf_recvlen == -1. I have not checked if data are accumulated
|
||||
to the right position in the buffer however. From Pavel Pisa
|
||||
(2015-08-21).
|
||||
* sched/wdog/wd_create.c: Correct a counting error in the number
|
||||
of available watchdog timers. When the number of free timers is
|
||||
low, the counter could be incremented below zero (2015-08-21).
|
||||
* arch/arm/src/stm32: Add OTG support for STM32F44x. From David
|
||||
Sidrane (2015-08-21).
|
||||
* arch/arm/src/lpc17: Actually implement options to use external
|
||||
SDRAM and or SRAM for the heap. From Pavel Pisa (2015-08-21).
|
||||
* gethostbyname(): correct returned address format when DNS is used.
|
||||
The hostent.h_addr_list should point to raw in_addr or in6_addr
|
||||
as defined in the standard. Original implementation used that
|
||||
for numeric addresses but for DNS lookup returned pointer to
|
||||
whole sockaddr_in or sockaddr_in6. From Pavel Pisa (2015-08-21).
|
||||
* tools/mksymtab: declare g_symtab array as const to occupy RO
|
||||
section (Flash). From Pavel Pisa (2015-08-23).
|
||||
* libc/libc.csv and syscalls/syscalls.csv: Define some symbol
|
||||
export conditions, correct errno and add sleep and usleep. From
|
||||
Pavel Pisa (2015-08-23).
|
||||
* net/ and include/nuttx/net: Remove references to PPP as a
|
||||
link layer protocol (2015-08-24).
|
||||
* net/, drivers/net, and include/net: Add definitions to support
|
||||
a local loopback device and link layer (2015-08-24).
|
||||
* libc/netdb, net/loopback, include/nuttx/net: Add NetDB support
|
||||
for the local loopback device (2015-08-24).
|
||||
* drivers/net/loopback.c: Add basic prototype of a local loopback
|
||||
device (2015-08-24).
|
||||
* networking: Correct return value from psock_tcp_accept(). From
|
||||
SaeHie Park (2015-08-25).
|
||||
* drivers/mtd/s25fl1.c: Add a driver for ST25L1*K QuadSPI parts
|
||||
(2015-08-25).
|
||||
* include/nuttx/spi/qspi.h: Develop a new interface for QSPI, at
|
||||
least the way that QSPI is implemented on the SAMV71. Originally
|
||||
planned to use the SPI interface, but it is just now compatible
|
||||
with the SAMV71 QSPI hardware (2015-08-25).
|
||||
* drivers/rwbuffer.c: Fix some logic errors. From Dmitry Nikolaev
|
||||
via Juha Niskanen (2015-08-26).
|
||||
* net/socket and net/tcp: Fix a problem in when there are multiple
|
||||
network devices. Polls were being sent to all TCP sockets before.
|
||||
This is not good because it means that packets may sometimes be
|
||||
sent out on the wrong device. That is inefficient because it
|
||||
will cause retransmissions and bad performance. But, worse, when
|
||||
one of the devices is not Ethernet, it will have a different MSS
|
||||
and, as a result, incorrect data transfers can cause crashes.
|
||||
The fix is to lock into a single device once the MSS is locked
|
||||
locked down (2015-08-27).
|
||||
* drivers/lcd and include/nuttx/lcd: Add SSD1351 OLED controller
|
||||
support. Contributed by Paul Alexander Patience (2015-08-28).
|
||||
* include/nuttx/mtd/mtd.h: Move MTD ioctl command definitions from
|
||||
include/nuttx/fs/fs.h to include/nuttx/mtd.h. Add ioctl commands
|
||||
to protect and unprotect memory (2015-08-29).
|
||||
* binfmt/builtin.c: Fix a memory leak: File was not being closed.
|
||||
From Bruno Herrera (2015-08-30).
|
||||
* fs/romfs: One allocation was not being freed if there was a
|
||||
subsequent failure to allocation I/O buffers resulting in a memory
|
||||
leak on certain error conditions. From Bruno Herrera (2015-08-30).
|
||||
* arch/arm/src/up_internal.h and several ARM Make.defs files: In the
|
||||
original implementation, !defined(CONFIG_ARMV7M_CMNVECTOR) was a
|
||||
sufficient test to determine if lazy floating point register saving
|
||||
was being used. But recents changes added common lazy register as
|
||||
well so now that test must be (!defined(CONFIG_ARMV7M_CMNVECTOR) ||
|
||||
defined(CONFIG_ARMV7M_LAZYFPU)) (2015-08-31).
|
||||
* arch/arm/include/sama5 and src/sama5: Add basic chip description,
|
||||
configuration support and interrupt definitions for the SAMA5D2
|
||||
(2015-08-31).
|
||||
* LPC43xx: Fix NVIC_SYSH_PRIORITY_STEP define. From Ilya Averyanov
|
||||
(2015-09-01).
|
||||
* LPC43xx: Fix missing #define in eeprom. From Ilya Averyanov
|
||||
(2015-09-01).
|
||||
* libc/math/lib_asin.c: The function did not convert for some input
|
||||
values. Asin did not convert for values which do not belong to the
|
||||
domain of the function. But aside of that the function also did not
|
||||
converge for some allowed values. I achieved a conversion of the
|
||||
function by reducing the DBL_EPSION and by checking if the input
|
||||
value is in the domain of the function. This is a fix for the
|
||||
problem but the function should always terminate after a given
|
||||
number of iterations. From Stefan Kolb (2015-09-01).
|
||||
* arch/arm/src/lpc43xx/lpc43_spi.c: Fix SPI driver. From Ilya
|
||||
Averyanov (2015-09-02).
|
||||
* arch/arm/src/lpc43xx/lpc43_ethernet.c: Add Ethernet support. From
|
||||
Ilya Averyanov (2015-09-02).
|
||||
* net/tcp: The logic that binds a specific network device to
|
||||
a connection was faulty for the case of multiple network
|
||||
devices. On bind(), the local address should be used to associate
|
||||
a device with the connection (if the local address is not INADDR_ANY);
|
||||
On connect(), the remote address should be used (in case the local
|
||||
address is INADDR_ANY). On accept(), it does not matter but the
|
||||
remote address is the one guaranteed to be available (2015-09-02).
|
||||
* configs/Board.mk and configs/*/src/Makefile: Simplify configs/
|
||||
Makefiles by combining common logic into a new Board.mk Makefile
|
||||
fragment. From Paul Alexander Patience (2015-09-04).
|
||||
* configs/sama5d2-xult: Add a very basic configuration for the SAMAD2
|
||||
Xplained Ultra board. This configuration is incomplete and only
|
||||
intended to support the initial board bring-up (2015-09-05).
|
||||
* up_initialize() all architectures: Automatically initialize all
|
||||
the TUN device if it is in the configuration (2015-09-06).
|
||||
* Change all references from avsprintf to vasprintf. From Sebastien
|
||||
Lorquet (2015-09-07).
|
||||
* net/tcp: Fix unbuffered send compilation error when Ethernet is not
|
||||
enabled. From Alan Cavalho de Assis (2015-09-07).
|
||||
* LPC31 and SAMA5D EHCI: Fix qh_ioccheck to move bp to next QH. From
|
||||
Ilya Averyanov (2015-09-07).
|
||||
* LPC31 and SAMA5D EHCI: Performance improvement: Do not disable the
|
||||
asynchronous queue when adding a new QH structure. From Ilya
|
||||
Averyanov (2015-09-07).
|
||||
* arch/arm/src/sama5: Separate memory mapping tables for SAMA5D2, 3,
|
||||
and 4 (2015-09-08).
|
||||
* libc/net/lib_shutdown.c: Add an empty implementation of the
|
||||
standard shutdown function. This provides only the framework for
|
||||
the shutdown function; the internal logic is not included
|
||||
(2015-09-09).
|
||||
* configs/nucleo-f303re: Support for the STMicro Nucleo F303RE board
|
||||
from Paul Alexander Patience (2015-09-10).
|
||||
* arch/arm/src/lpc43xx/lpc32_ehci.c and .h: LPC43xx EHCI driver from
|
||||
Ilya Averyanov (2015-09-10).
|
||||
* ARMv7-M, all "lazy" interrupt stack logic. Assembly instruction
|
||||
that fetches the saved value is incorrect; replace with more
|
||||
traditional push and pop. This is an important fix. Noted by
|
||||
Stefan Kolb (2015-09-14).
|
||||
* All ARMV7-M: Force 8-byte stack alignment when calling from assembly
|
||||
to C to interrupt handling (2015-09-15).
|
||||
* drivers/power/battery_gauge.c and include/nuttx/power/battery_gauge.h:
|
||||
battery.c/h renamed to batter_gauge.c/.h since it really only
|
||||
implements a battery fuel gauge. From Alan Carvalho de Assis (2015-09-19).
|
||||
* drivers/power/battery_charger.c and include/nuttx/power/batter_charger.h:
|
||||
Add a new framework to support a batter charger interface. From Alan
|
||||
Carvalho de Assis (2015-09-19).
|
||||
* drivers/power/bq2425x.c and .h: Battery Charger: Add BQ24250 driver.
|
||||
From Alan Carvalho de Assis (2015-09-20).
|
||||
* fs/mqueue/mq_open.c: When message queue is opened, inode_reserve()
|
||||
leaves the reference count at zero. mq_open() logic must assure
|
||||
that the reference count of the newly created inode is one (2015-09-23).
|
||||
* arch/sim/src/Kconfig, Makefile, up_setjmp64.S: Modern Cygwin X86_64
|
||||
machines follow the Microsoft ABI for parameter passing. The older,
|
||||
Linux System 5 ABI will not work on X86_64-based Cygwin machines. Also,
|
||||
the newer Cygwin tool chains do nor pre-pend symbol names with the
|
||||
underscore character. With these changes the simulator agains works
|
||||
with the newer Cygwin64 platform (2015-09-24).
|
||||
* arch/arm/src/lpc43xx: Extensive I2C and clocking updates from Lok Tep
|
||||
(2015-09-29).
|
||||
* configs/lpc4370-link2: Support for the NXP LPC4370-Link2 development
|
||||
board from Lok Tep (2015-09-29).
|
||||
* configs/nucleo-f303re: Add SSD1351 SPI 4-wire interface. From Paul
|
||||
Alexander Patience (2015-09-29).
|
||||
* arch/arm/src/armv7-m/up_schedulesigaction.c: Fix logic that determines
|
||||
if there is a pending signal action before scheduling the next signal
|
||||
action. Both the test and the scheduling action need to be atomic
|
||||
(2015-09-30).
|
||||
* sched/wqueue/kwork_queue.c and libc/wqueue/work_queue.c: Logic that
|
||||
sets the queued indication and the logic that does the actual queuing
|
||||
must be atomic (2015-09-20).
|
||||
|
||||
7.13 2015-12-05 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* libc/stdlib/lib_bsearch.c and include/stdlib.h: Add the bsearch()
|
||||
function from NetBSD (2015-10-02).
|
||||
* libc/stdlib/lib_qsort.c and include/stdlib.h: Make coding style
|
||||
more conformant, take description from OpenGroup.org, rename formal
|
||||
parameters to match names used on OpenGroup.org (2015-10-02).
|
||||
* drivers/lcd/st7565.c: Extend to include support for the ERC12864-3.
|
||||
From Pierre-noel Bouteville (2015-10-07).
|
||||
* fs/tmpfs: Created a directory that will eventually hold a trivial
|
||||
temporary RAM file file system (2015-10-0i8).
|
||||
* tools/: Add crappy style checking tool nxstyle.c. See thee tools/
|
||||
README file for more info (2015-10-08).
|
||||
* stm32 F4: Fix some TIM12 pin mappings. From Max Kriegleder
|
||||
(2015-10-9).
|
||||
* fs/tmpfs: TMPFS file system is code complete and bascially functional
|
||||
although it has not been heavily tested (2015-10-9).
|
||||
* drivers/input/button_upper.c and include/nuttx/input/buttons.h: Add a
|
||||
driver to support application access to board buttons (2015-10-12).
|
||||
* drivers/input/button_lower.c: Add a generic lower half button driver.
|
||||
This lower half driver is only usable in a limited number of
|
||||
situations, but can still serve as a module for the lower half button
|
||||
driver. (2015-10-13).
|
||||
* drivers/sensors/zerocross.c and include/nuttx/sensors/zerocross.h:
|
||||
Add Zero Cross device driver support. From Alan Carvalho de Assis
|
||||
(2015-10-13).
|
||||
* configs/stm32f4discovery/src/stm32_zerocross.c: Add low level support
|
||||
for the Zero Cross driver for the STM32F4-Discovery. From Alan
|
||||
Carvalho de Assis (2015-10-13).
|
||||
* drivers/sensors/max6675.c and include/nuttx/sensors/max6675.h: Add
|
||||
support to Thermocouple-to-Digital converter MAX6675. From Alan
|
||||
Carvalho de Assis (2015-10-18).
|
||||
* configs/stm32f4discovery/src: Add board config to support MAX6675.
|
||||
From Alan Carvalho de Assis (2015-10-18).
|
||||
* arch/arm/src/samv7/sam_lowputc.c: Reconfigure System I/O when using
|
||||
USART1. From Frank Benkert (2015-10-20).
|
||||
* fs/semaphore: Named semaphores: Bad cast in sem_close(). Fixed by
|
||||
reordering fields of struct nsem_inode_s so that the cast will work
|
||||
(2015-10-22).
|
||||
* Many files: Rename board_led_* functions to board_autoled_* functions.
|
||||
This makes room in the namespace to handler user LED functions
|
||||
(2015-11-01).
|
||||
* Many files: Standardize naming of the user LED interface functions.
|
||||
The new user LED interface functions are now prototyped in only in
|
||||
include/nuttx/board.h and have name like board_userled_* (2015-11-01).
|
||||
* drivers/leds/usersled_upper.c and include/leds/usersled.h: Add
|
||||
a generic character driver that may be used by applications to write
|
||||
to board LEDs (2015-11-01).
|
||||
* drivers/leds/usersled_lower.c: Add a generic lower-half user LED
|
||||
driver that may be used by any board that supports the standard
|
||||
board user LED interfaces (2015-11-01).
|
||||
* sched/clock: Fix error in clock_timespec_subtract(). Found by Lok
|
||||
(2015-11-03).
|
||||
* drivers/can.c and include/nuttx/can.h: Fix a problem in the CAN
|
||||
upper-half driver that occurs only for CAN hardware that support a
|
||||
H/W FIFO of outgoing CAN messages. In this case, there can be a
|
||||
hang condition if both the H/W and S/W FIFOs are both full. In that
|
||||
case, there may be no event to awaken the upper half driver. Add a
|
||||
new (conditional) CAN upper half interface called can_txready() that
|
||||
can be used by the lower half driver to avoid this hang condition
|
||||
(2015-11-03).
|
||||
* arch/arm/src/samv7: Add a call to can_txready() to the MCAN driver
|
||||
(2015-11-03).
|
||||
* arch/arm/src/samv7: Add MPU and protected build support (2015-11-06).
|
||||
* arch/arm/src/samv7: The QSPI FLASH driver is now functional. This
|
||||
driver operates in the memory-mapped, Serial Memory Mode (SMM)
|
||||
(2015-11-07).
|
||||
* drivers/bch: Block-to-character (BCH) driver should forward ioctl()
|
||||
calls to the contained block driver (2015-11-09).
|
||||
* arch/arm/samv7/sam_qspi.c: The QuadSPI driver is now functional
|
||||
(2015-11-10).
|
||||
* drivers/mtd/s25fl1.c: The S25FL1xx QuadSPI FLASH driver is now
|
||||
functional (2015-10-11).
|
||||
* arch/arm/samv7: Add an on-chip FLASH driver (2015-11-12).
|
||||
* drivers/mtd/mtd_progmem.c: Add an upper half MTD device that can
|
||||
use the interfaces defined in included/nuttx/progmem.h to provide
|
||||
a standard MTD interface (2015-11-12).
|
||||
* drivers/serial/serial.c, serialirq.c and include/nuttx/serial/serial.h:
|
||||
Implement high level DMA infrastructure for serial devices. From
|
||||
Max Neklyudov (2015-11-12).
|
||||
* arch/arm/src/samv7 and arch/arm/include/samv7: Add support for the
|
||||
SAME70 family of chips (2015-11-14).
|
||||
* configs/stm32f429i-disco: configs/stm32f429i-disco/src/stm32_nsh.c
|
||||
file calculated partition boundries based on page block sizes but
|
||||
mtd_partition() is expecting calculations based on erase block size.
|
||||
From Alan Carvalho de Assis (2015-11-16).
|
||||
* Move rivers/wireless/cc3000/security.c to crypto/aes.c; move
|
||||
include/nuttx/wireless/cc3000/security.h to include/nuttx/crypto/aes.h
|
||||
(2015-11-16).
|
||||
* drivers/mtd/at24xx.c: Add support for multiple AT24xx EEPROM parts,
|
||||
each with unique I2C addresses, but otherwise identical (2015-11-17).
|
||||
* drivers/timers/ds3231.c: Add support for the DS3231 I2C RTC. Untested
|
||||
on the initial commit (2015-11-17).
|
||||
* arch/arm/src/stm32/stm32_tim_lowerhalf.c: Add a compatible lower-half
|
||||
timer driver for use with drivers/timers/timer.c. From Wail Khemir
|
||||
(2015-11-17).
|
||||
* drivers/sensors/ms58xx.c: Fix some issues with initialization and with
|
||||
CRC calculation. From Karim Keddam (2015-11-17).
|
||||
* drivers/mtd/w25.c: Fix W25 FLASH driver page read/write logic. From
|
||||
Ken Pettit (2015-11-18).
|
||||
* drivers/mtd/smart.c: Fix a Smart wear-leveling bug. From Ken Pettit
|
||||
(2015-11-18).
|
||||
* arch/sim/src/up_spiflash.c: Add support for W25 FLASH simulation.
|
||||
From Ken Pettit (2015-11-18).
|
||||
* configs/boardctl.h, Kconfig, include/sys/boardctl.h, and nuttx/board.h:
|
||||
Add a command to the boardctl() interface to obtain a board unique ID
|
||||
(2015-11-18).
|
||||
* drivers/timers/ds3231.c: Driver extended to include support for the
|
||||
DS1307 RTC (2015-11-18).
|
||||
* configs/same70-xplained: Add basic NSH configuration for the SAME70
|
||||
Xplained board. Initial commit is just the SAMV71-XULT files with
|
||||
names changed appropriately (2015-11-18).
|
||||
* drivers/mtd/smart.c: Fixed SmartFS wear level error that occurs when
|
||||
the logical sector size is too small to save all wear level status
|
||||
bytes in a single sector. Logical sectors 1 and 2 were simply not
|
||||
being allocated and then the read_sector and write_sector routines
|
||||
were failing. From Ken Pettit (2015-11-18).
|
||||
* drivers/timers/ds3231.c: Untested support for DS1302 and DS3232.
|
||||
Also definitions for the DS3234, but that is an unsupported SPI RTC
|
||||
(2015-11-19).
|
||||
* drivers/mtd/w25.c: Add support for byte write mode. From Ken Pettit
|
||||
(2015-11-20).
|
||||
* drivers/timers/pcf85263.c and include/nuttx/times/pcf85263.h: Add
|
||||
a driver for the NXP PCF85263 I2C RTC. Untested on initial commit
|
||||
(2015-11-20).
|
||||
* fs/driver/fs_blockproxy.c: Add logic to create a temporary char driver
|
||||
using drivers/bch to mediate character oriented accessed to a block
|
||||
driver (2015-11-21).
|
||||
* fs/vfs/open.c: If the use attempts to open a block driver, use
|
||||
block_proxy() to insert a character driver conversion layer in front
|
||||
of the block driver (2015-11-21).
|
||||
* libc/stdio/lib_freopen.c and include/stdio.h: Add support for
|
||||
freopen() (2015-11-22).
|
||||
* include/sys/types.h and include/nuttx/mm.h: When building on a 64-bit
|
||||
machine, the size of size_t should be 64-bits. In general, I believe
|
||||
that sizeof(size_t) should be the same as sizeof(uinptr_t). mmsize_t
|
||||
should always be 32-bits in any event. The last change to stddef has
|
||||
been backed out. With these changes, the simulator builds without
|
||||
* fs/hostfs and arch/sim/src: Add a special file system for use with
|
||||
simulator that supports access to the host file system from the
|
||||
simulation. From Ken Pettit (2015-11-25).
|
||||
* libc/time/lib_strftime.c: Add day-of-week support. (2015-11-25).
|
||||
* drivers/lcd/ili9432.c: Fixed errors in orientation. Portrait,
|
||||
RPortrait, and RLandscript should work correly now. They were
|
||||
displayed mirrored. From Marco Krahl (2015-11-25).
|
||||
* drivers/mtd/mtd/mtd_procfs/c and include/nuttx/mtd/mtd.h: Add an
|
||||
interface to un-register an MTD procfs entry. From Ken Pettit
|
||||
(2015-11-25).
|
||||
* drivers/mtd/filemtd.c: A new MTD conversion layer that will
|
||||
convert a regular file (or driver file) to an MTD device. This is
|
||||
useful for testing on the simulation using the hostfs. From Ken
|
||||
Pettit (2015-11-25).
|
||||
* drivers/loop: Add a loop character device. losetup() and
|
||||
loteardown() should not be called directory from applications.
|
||||
Rather, these functions are now available as IOCTL commands to the
|
||||
loop driver (2015-11-25).
|
||||
* include/nuttx/net/netdev.h and several Ethernet drivers in arch/:
|
||||
Most network drivers do not support statistics. Those that do only
|
||||
support them when DEBUG is enabled. Each driver collects an
|
||||
architecture specific set of statistics and there is no mechanism in
|
||||
place to view those statistics. Thus, the driver feature was mostly
|
||||
useless. This change standardizes the driver statistics and puts the
|
||||
definition in the common network device structure defined in netdev.h
|
||||
where they can be accessed by network applications. All Ethernet
|
||||
drivers that collect statistics have been adapted to use these common
|
||||
statistics (2015-11-26).
|
||||
* net/net_procfs.c: Add basic support for networking entries in the
|
||||
procfs (2015-11-27).
|
||||
* mtd/filemtd.c and smart.c: Add support for a /dev/smart loop device.
|
||||
From Ken Pettit (2015-11-28).
|
||||
* sched/pthread/: CRITICAL BUGFIX: Logic was wiping out the indication
|
||||
that of the type of a pthread. Hence, it could be confused as a
|
||||
task. Found because this was causing a crash when /proc/nnn/cmdline
|
||||
was printed (2015-11-29).
|
||||
* configs/same70-xplained/nsh: The NSH configuration now seems fully
|
||||
functional: serial console, LEDs, buttons, SDRAM, and HSMCI SD card
|
||||
(2015-11-30).
|
||||
* configs/same70-xplained/netnsh: Added and verified a network-enabled
|
||||
NSH configuration for the SAME70-Xplained board (2015-11-20).
|
||||
* net/: Remove CONFIG_NET_PINGADDRCONF. This was a uIP way of assigning
|
||||
IP addresses, but is not standard and not a appropriate feature in
|
||||
general (2015-12-01).
|
||||
* fs/procfs: The procfs file system can now be configured so that it
|
||||
supports a runtime registration of procfs entries with
|
||||
CONFIG_FS_PROCFS_REGISTER=y (2015-12-01).
|
||||
* arch/arm/src/stm32/stm32_ccm_procfs.c: Is no longer a part of the
|
||||
'base' procfs entries and can now only be supported via run time
|
||||
registration with CONFIG_FS_PROCFS_REGISTER=y (2015-12-01).
|
||||
* arch/arm/src/samv7/sam_tc.c: Port the SAMA5 timer/counter driver
|
||||
to the SAMV7 (2015-12-02).
|
||||
* arm/arm/src/samv7/sam_tickless.c: Port the SAMA5/SAM4CM tickless
|
||||
logic to the SAMV7 (2015-12-02).
|
||||
* fs/semaphore: Named semaphores: Back out "fix" of 2015-10-22. It was
|
||||
correct before. The change of 2015-10-22 probably broke named
|
||||
semaphores (2015-12-02).
|
||||
* arch/arm/src/samv7: Bring programmable clock logic from SAMA5 into
|
||||
SAMV7 (2015-12-03).
|
||||
* arch/arm/src/samv7: Add PCK6 as an optional source for the timer/
|
||||
counter clock (2015-12-04).
|
||||
* configs/samv7-xult/: If Tickless mode is selected then enable PCK6
|
||||
as a timer/counter clock source (2015-12-04).
|
||||
|
||||
7.14 2016-01-28 Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* arch/arm/src/samv7: Port the TRNG driver from the SAMA5D3/4 to the
|
||||
SAMV7 (2015-12-06).
|
||||
* arch/arm/src/samv7: Port the WDT driver from the SAMA5D3/4 to the
|
||||
SAMV7 (2015-12-06).
|
||||
* arch/arm/src/samv7: Add an RSWDT driver (2015-12-06).
|
||||
* drivers/net/telnet.c: Move the Telnet driver from apps/netutils/telnetd
|
||||
to drivers/net. It is a driver a belongs in the OS. There are still
|
||||
some interface related issues, however (2015-12-07).
|
||||
* configs/: Update all configurations that use the Telnet daemon; those
|
||||
configurations now need to separately enable the Telnet drvier
|
||||
(2015-12-07).
|
||||
* drivers/net/telnet.c: Now works like the loop device. A new interface
|
||||
called telnet_initialize() registers a telnet session "factory"
|
||||
device at /dev/telnet. Via ioctl, the factory device can create
|
||||
instances of the telnet character devices at /dev/telnetN to support
|
||||
Telnet sessions (2015-12-07).
|
||||
* arch/arm/src/samv7: In USBHS device driver, fix check if zero length
|
||||
packet is needed (2015-12-08).
|
||||
* sched/pthread/: CRITICAL BUGFIX: Logic was wiping out the indication
|
||||
that of the type of a pthread. Hence, it could be confused as a
|
||||
task. Same problem as fixed on 2015-11-29, but in different location
|
||||
(2015-12-09).
|
||||
* sched/module: Add support for kernel modules. Initial commit is
|
||||
just the ELF module support with name changes (2015-12-10).
|
||||
* configs/samv71-xult/module: Add configuration for testing OS
|
||||
modules (2015-12-12).
|
||||
* sched/module: Add an implementation of rmmod() (2015-12-12).
|
||||
* sched/module and fs/procfs: Add some basic module procfs support
|
||||
(2015-12-12),
|
||||
* arch/arm/src/armv7-r: Add basic architecture support for the ARMv7-R
|
||||
processor family (2015-12-13).
|
||||
* drivers/led: Adds a driver for the PCA9635PW I2C LED driver IC which
|
||||
can be used to control the intensity of up to 16 LEDs. From Alexander
|
||||
Entinger (2015-12-15).
|
||||
* configs/launchxl-tms57004: Add basic board support for TI LaunchXL-
|
||||
TMS57004. Not much to see there yet (2015-12-15).
|
||||
* waitpid: CRITICAL BUGFIX. Add a reference count to prevent waitpid
|
||||
from using stale memory released by the waited-for task group
|
||||
(2015-12-22).
|
||||
* sys/time.h: Add timeradd(), timersub(), timerclear(), timerisset(),
|
||||
and timercmp() as macros. These are non-POSIX interfaces, but
|
||||
included in most BSD deriviatives, including Linux. From Manuel Stühn
|
||||
(2015-12-23).
|
||||
* arch/arm/src/stm32: Add timer input capture driver. From Pierre-Noel
|
||||
Bouteville (2015-12-24).
|
||||
* arch/avr: Add support for the Atmega2560. From Dimitry Kloper
|
||||
(2015-12-19).
|
||||
* configs/arduino-mega2560: Add support for the Arduino-Mega2560. From
|
||||
Dimitry Koper (2015-12-29).
|
||||
* sched/signal, sched/mqueue, sched/timer, include/signal.h,
|
||||
include/nuttx/signal, fs/aio, libc/aio, and probably other
|
||||
directories: Add support for the SIGEV_THREAD notification method in
|
||||
struct sigevent. This initial implementation will only work in the
|
||||
FLAT build. See the top-level TODO file for additional details
|
||||
(2015-12-30).
|
||||
* include/nuttx/compiler.h, include/nuttx/streams.h include/stdio.h
|
||||
include/syslog.h libc/stdio/, and libc/syslog: introduce support for
|
||||
Atmel toolchain in-flash strings. Atmel toolchain AVR compiler
|
||||
provides a transparent in-flash object support using __flash and
|
||||
__memx symbols. The former indicates to compiler that this is a flash-
|
||||
based object. The later used with pointer indicates that the referenced
|
||||
object may reside either in flash or in RAM. The compiler automatically
|
||||
makes 32-bit pointer with flag indicating whether referenced object is
|
||||
in flash or RAM and generates code to access either in run-time. Thus,
|
||||
any function that accepts __memx object can transparently work with RAM
|
||||
and flash objects.
|
||||
For platforms with a Harvard architecture and a very small RAM like AVR
|
||||
this allows to move all constant strings used in trace messages to flash
|
||||
in the instruction address space, releasing resources for other things.
|
||||
This change introduces IOBJ and IPTR type qualifiers. The 'I' indicates
|
||||
that the object may lie in instruction space on a Harvard architecture
|
||||
machine. For platforms that do not have __flash and __memx or similar
|
||||
symbols IOBJ and IPTR are empty, making the types equivalent to, for
|
||||
example, 'const char' and 'const char*'. For Atmel compiler these will
|
||||
become 'const __flash char' and 'const __memx char*'. All printf()
|
||||
functions and syslog() functions are changed so that the qualifier is
|
||||
used with the format parameter. From Dimitry Kloper (2016-01-05).
|
||||
* drivers/net/tun.c: Fix a compile time error in the TUN driver. From
|
||||
Vladimir Komendantskiy (2016-01-05).
|
||||
* Kconfig and include/debug.h: Add configuration to support an
|
||||
architecture-specific debug.h header file. From Dimitri Kloper
|
||||
(2016-01-09).
|
||||
* arch/avr/include/debug.h: Add an AVR-specific header file used when
|
||||
the AVR MEMX pointer is used. From Dimitri Kloper (2016-01-09).
|
||||
* tools/cnvwindeps.c: Add a tool that will convert paths in
|
||||
dependencies generated by a Windows compiler so that they can be
|
||||
used with the Cygwin make (2016-01-09).
|
||||
* tools/mkwindeps.sh: A script that coordinates use of cnvwindeps.exe
|
||||
(2016-01-09).
|
||||
* tools/mkdeps.c: Deleted mkdeps.sh and mkdeps.bat. The mkdeps
|
||||
executable generated from mkdeps.c is now that the only supported
|
||||
way to make dependencies (2016-01-09).
|
||||
* tools/mkdeps.c: Extended/fixed support for --winpath option.
|
||||
Dependencies now work under Cygwin with a native Windows toolchain
|
||||
(2016-01-10).
|
||||
* libc/netdb: Add support for the use of a DNS resolver file like
|
||||
/etc/resolv.conf (2016-01-14).
|
||||
* drivers/sensors/mcp9844.c and include/nuttx/sensors/mcp9844.h: Driver
|
||||
for the MCP9844 I2C digital temperature sensor with a selectable
|
||||
resolution. From Alexander Entinger (2016-01-15).
|
||||
* arch/arm/src/lpc43xx: Numerous LPC43 improvements to SPIFI and ADC
|
||||
from Lok Tep (2016-01-15).
|
||||
* configs/lpc4337-ws: Support for the WaveShare LPC4337-WS board. From
|
||||
Lok Tep (2016-01-15).
|
||||
* drivers/wireless/pn532.c: Add driver for the NXP pn532 NFC-chip. From
|
||||
Janne Rosberg and others at Offcode Ltd (2016-01-17).
|
||||
* drivers/sensors/lsm9ds1.c: Add driver for the STMicro LSM9DS1 chip.
|
||||
The LSM9DS1 is a system-in-package featuring a 3D digital linear
|
||||
acceleration sensor, a 3D digital angular rate sensor, and a 3D
|
||||
digital magnetic sensor. From Paul Alexander Patience (2016-01-17).
|
||||
* configs/olimex-stm32-h407: Added a port to the Olimex STM32 H407
|
||||
board. This board features the STMicro STM32F407ZGT6 (144 pins).
|
||||
Contributed by Neil Hancock. (2016-01-18)
|
||||
* arch/arm/src/stm32/stm32_otgfs/hs/host.c: Fix some backward
|
||||
arguments to stm32_putreg(). Note by Hang Xu (2016-01-18).
|
||||
* include/nuttx/can.h and several CAN drivers: Add more extensive
|
||||
error reporting capaibility to the CAN interface. From Frank
|
||||
Benkert (2016-01-18).
|
||||
* libc/misc/lib_tea.h and include/nuttx/crypto/tea.h: Add an
|
||||
implementation of the Tiny Encryption Algorithm (2016-01-19).
|
||||
* sim/include: Now supports a customizable startup script with a
|
||||
read-only passwd file (2016-01-20).
|
||||
* sim/nsh: Uses the custom start up script, includes hooks for
|
||||
an MOTD message. (2016-01-20).
|
||||
* include/clock.h and lots of other files: If the 64-bit timer is
|
||||
selected, then use it whenever clock_systimer() is called rather
|
||||
then chopping the 64-bit timer down to 32-bits. Add a new type,
|
||||
systime_t to represent the 32- or 64-bit system timer (2016-01-21).
|
||||
* sched/clock/clock_systimespec.c: Fix an error in a time
|
||||
conversion (2016-01-21).
|
||||
* include/nuttx/clock.h: Get rid of clock_systimer32() and
|
||||
clock_systime64(). There is now only clock_systimer() (2016-01-21).
|
||||
* arch/arm/src/kinetis: Numerous updates to the Kinetis ENET driver.
|
||||
From Andrew Webster (2016-01-21).
|
||||
* arch/arm/src/kinetis: Add support for the MK60N512VLL100 Kinetis part.
|
||||
From Andrew Webster (2016-01-21).
|
||||
* net/tcp and net/iob: Numerous fixes, mostly relate to TCP and IOB
|
||||
buffering and race conditions. These were necessary for for the
|
||||
NuttX networking later to be stable in some stress testing. From
|
||||
Andrew Webster (2016-01-22).
|
||||
* include/spi/spi.h: Add an optional hwfeatures() method to the
|
||||
SPI interface (2016-01-23).
|
||||
* drivers/spi/Kconfig and many other files: Remove CONFIG_SPI_OWNBUS:
|
||||
Now its not just a good idea, its the law (2015-01-23).
|
||||
* include/nuttx/math32.h and libc/misc: Add some utilities to support
|
||||
64-bit arithmetic operations for platforms that do not support long
|
||||
long types. Not yet used anywhere (2015-01-25).
|
||||
* arch/arm/src/samv7/chip: Add an AFEC header file (2016-01-25).
|
||||
* net/iob: iob_alloc_qentry() has the same issues as did iob_alloc()
|
||||
fixed on 2016-01-23. (2016-01-26).
|
||||
* drivers/usbhost/hid_parser.c: Wrong size used in memcpy(). From Hang
|
||||
Xu (2016-01-25).
|
||||
* drivers/ioexpander/pca9555.c: Fixed a bug in the function pca9555_setbit
|
||||
which occurs if someone tries to set one of the pins 8-15. The problem is
|
||||
that after the check if the pin is greater than 7 the variable addr is
|
||||
incremented and used in the Call I2C_WRITEREAD. But later in the call to
|
||||
the I2C_WRITE buf[0] is used as address but this address is not incremented
|
||||
as it should be. Note address does mean the address to the register in the
|
||||
ioexpander and not the I2C address. From Stefan Kolb (2016-01-26).
|
||||
* drivers/ioexpander/pca9555: Convert to use I2C_TRANSFER vs. I2C_WRITEREAD,
|
||||
the former is thread safe while the latter is deprecated (2016-01-26).
|
||||
* drivers/i2c/i2c_writeread.c: Create a wrapper that uses I2C_TRANSFER
|
||||
to implement I2C_WRITEREAD functionality (2016-01-26).
|
||||
* I2C: Eliminate the I2C_WRITEREAD method (2016-01-26).
|
||||
* drivers/i2c/i2c_read.c and i2c_write.c: Convert to use I2C_TRANSFER vs.
|
||||
I2C_READ and I2C_WRITE which are not thread safe (2016-01-26).
|
||||
* SPI: Rename the STM32 up_spiinitialize() to stm32_spibus_initialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename the SAM up_spiinitialize() to stm32_spibus_initialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename the Tiva up_spiinitialize() to tiva_spibus_intialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename the PIC32MX/MZ up_spiinitialize() to pic32mx/mz_spibus_intialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename EFM32's efm32_spi_initialize to efm32_spibus_initialize()
|
||||
for compatibility with these other changes (2016-01-26).
|
||||
* SPI: Rename the KL up_spiinitialize() to kl_spibus_intialize() (2016-01-26).
|
||||
* SPI: Rename the Kinetis up_spiinitialize() to kinetis_spibus_intialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename the LPC31xx up_spiinitialize() to lpc31_spibus_intialize(),
|
||||
Rename the LPC17xx lpc17_spiinitialize() to lpc31_spibus_intialize(),
|
||||
Rename the LPC43xx up_spiinitialize() to lpc43_spibus_intialize()
|
||||
(2016-01-26).
|
||||
* SPI: Rename the AVR up_spiinitialize() to avr_spibus_intialize(),
|
||||
Rename the LPC2148 up_spiinitialize() to lpc214x_spibus_intialize(),
|
||||
Rename the Calypso up_spiinitialize() to calypso_spibus_intialize(),
|
||||
Rename the ez80 up_spiinitialize() to ez80_spibus_intialize(),
|
||||
Rename the STR71xx up_spiinitialize() to str71_spibus_intialize(),
|
||||
Rename the i.MX1 up_spiinitialize() to imx_spibus_intialize(),
|
||||
Rename the LPC2378 up_spiinitialize() to lpc23_spibus_intialize(),
|
||||
Rename the M9S12 up_spiinitialize() to hcs12_spibus_intialize(),
|
||||
Rename the x86 up_spiinitialize() to i486_spibus_intialize(),
|
||||
Rename the z16f up_spiinitialize() to z16_spibus_intialize().
|
||||
up_spiinitialize() has been completely eliminated. (2016-01-27).
|
||||
* fs/vfs/fs_poll.c: Fix handling of sem_tickwait() return value
|
||||
sem_tickwait() does not return an -1+errno, it returns a negated
|
||||
errno value. Noted by Freddie Chopin.
|
||||
|
||||
7.15 2016-xx-xx Gregory Nutt <gnutt@nuttx.org>
|
||||
|
||||
* drivers/analog/adc1242.c and include/nuttx/analog/adc1242.h: Driver
|
||||
for the 24-Bit Differential Input ADC ADS1242 that communicates via
|
||||
SPI with a MCU. Reading the ADC conversion result as well as configuring
|
||||
the ADC, setting the input channel, etc. is implemented via ioctl calls.
|
||||
However, it does not yet implement the standard ADC interface. From
|
||||
* configs/board/src/xyz_cxxinitialize.c: Move CXX initialization logic
|
||||
out of the RTOS and into the application space, specifically to
|
||||
apps/platform/board, where it belongs (2016-01-29).
|
||||
* drivers/modem/u-blox.c and include/nuttx/drivers/u-blox.h: Add an upper
|
||||
half driver for the U-Blox Modem. From Vladimir Komendantskiy
|
||||
(2018-01-30).
|
||||
* arch/arm/src/lpc17xx: Backport lpc43xx I2C driver, replacing the
|
||||
lpc17xx I2C driver. This gives us the I2C_TRANSFER method (2016-01-30).
|
||||
* arch/arm/src/lpc11xx: Backport the lpc17xx I2C driver, replacing the
|
||||
lpc11xx I2C driver. This gives us the I2C_TRANSFER method (2019-01-30).
|
||||
* arch/arm/src/lpc2378: Backo the Lpc17xx I2C driver, replacing the
|
||||
lpc2378 I2C driver. This gives us the I2C_TRANSFER method (2019-01-30).
|
||||
* confgs/u-blox-c027: Support for the u-blox GSM and GPS module evaluation
|
||||
board with NXP LPCExpresso LPC1768. The GSM module is one of LISA-C200,
|
||||
LISA-U200 or SARA-G350. The GPS module is one of MAX-M7 or MAX-M8. From
|
||||
Vladimir Komendantskiy (2016-01-31).
|
||||
* drivers/, arch/, include/, numerous files: May restructuring of the I2C
|
||||
interface necessary to eliminate some thread-safety issues inherent in
|
||||
the legacy I2C interface design. This effects the interface definition,
|
||||
all I2C clients, and all low-level I2C drivers. I have used caution,
|
||||
but I still expect a change of this magnitude to introduce some errors.
|
||||
Any bug reports of bug fixes will be much appreciated (2016-02-01).
|
||||
* drivers/i2c/i2c_driver.c: Add an I2C character drivers to support
|
||||
raw I2C data transfers for test applications (2016-02-02).
|
||||
* I2C_RESET: Eliminate up_i2creset(). It should not be a global function;
|
||||
Now it is an I2C interface method (2016-02-02).
|
||||
* I2C: Rename up_i2cinitialize and up_i2cuninitilize to follow the correct
|
||||
naming convention. These are not common interfaces used by the OS;
|
||||
these are MCU-specific interfaces used only be MCU-specific code. The
|
||||
the correct naming is xyz_i2cbus_initialize and xzy_i2cbus_uninitialize
|
||||
where xzy is the MCU mnemonic (2016-02-02).
|
||||
* Networking drivers that support CONFIG_NET_NOINTS: Fix a race condition
|
||||
that can cause the TX poll timer to stop running. From Manuel Stuhn
|
||||
(2016-02-03).
|
||||
* All Network drivers: Remove the hsec parameter from devif_timer().
|
||||
We can get better timing accuracy without it (2016-02-03).
|
||||
* drivers/ioexpander/pca555.c: Add logic to make the PCA555 driver
|
||||
thread safe (2016-02-03).
|
||||
* sched/init/os_start.c and include/nuttx/init.h: Add a state variable
|
||||
that provides the current level of OS initialization. This is needed by
|
||||
some logic that may attempt to run early in the start-up sequence but
|
||||
cannot run if a sufficient level of initialization has not yet occurred
|
||||
(2016-02-05).
|
||||
* libc/syslog/lib_syslog.c: If syslog timestamping is enabled, don't try to
|
||||
get the time if the timer hardware has not yet been initialized
|
||||
(2016-02-05).
|
||||
* fs/procfs/fs_procfskmm.c: Add /proc/kmm entry that shows that state of
|
||||
the kernel heap. Only useful in PROTECTED and KERNEL build modes where
|
||||
there is a kernel heap (2016-02-06).
|
||||
* sched/ and arch/: Replace explicit access to the OS internal data structure
|
||||
g_readytorun() with the wrapper this_task() which hides the implementation
|
||||
and will permit such things as more scalable representations of task queues
|
||||
and SMP (2016-02-06).
|
||||
* include/nuttx/net/arp.h, include/nuttx/net/ioctl.h, net/netdev/netdev_ioctl.c,
|
||||
and ARP-related files: Add support for IOCTL commands to manage the
|
||||
ARP table (2016-02-08).
|
||||
* ARMv7-A, ARMv7-R, and ARMv7-A: Add test-and-set logic and definitions
|
||||
needed to supports spinlocks (2016-02-09).
|
||||
* include/nuttx/spinlock.h: Add basic definitions for spinlocks. Not yet
|
||||
used by NuttX (2016-02-09).
|
||||
* include/nuttx/arch.h, sched/sched/sched.h: Add some basic definitions
|
||||
that may be needed for SMP support (2016-02-10).
|
||||
* sched/init/os_start.c, sched/init/os_smpstart.c, and include/nuttx/arch.h:
|
||||
Add some tentative SMP start-up logic (2016-02-10).
|
||||
* arch/arm/sim/up_head.c and up_simsmp.c: Add multi-CPU support to the
|
||||
simulation to support SMP investigation.. Currently crashes when CONFIG_SMP
|
||||
is enabled as expected (2016-02-10).
|
||||
* sched/sched.h and other files: Replace the bool 'prioritized' in the task
|
||||
list table with a uint8_t bit set so that additional attributes of a task
|
||||
list can be provided without adding more booleans (2016-10-11).
|
||||
* Everywhere: Replace irqsave() with enter_critical_section(); replace
|
||||
irqrestore() with leave_critical_section(). This is part of the onging
|
||||
development of SMP support (2016-02-13).
|
||||
* Conform to naming convention: Rename irqsave() to up_irq_save(); rename
|
||||
irqrestore() to up_irq_restore(). These should no longer be used. If
|
||||
your code still uses them, please switch to enter_critical_section()
|
||||
and leave_critical_section() (2016-02-14).
|
||||
* Also rename irqdisable() and irqenable() to up_irq_disable() and
|
||||
up_irq_enable() (2016-02-14).
|
||||
* sched/signal and include/nuttx/sched.h: Move the list of signal
|
||||
actions from the TCB to the group structure. Signal handlers are not
|
||||
per thread but, rather, per task group. I know, I preferred it the
|
||||
other way too, but this is more compliant with POSIX (2016-02-18).
|
||||
* fs/ procfs/fs_procfsproc.c: Add support for showing CPU if SMP is
|
||||
is enabled (2016-02-19).
|
||||
* include/pthread.h, sched.h, sys/types.h and other files: Rename
|
||||
cpuset_t to cpu_set_t which is the type used in some non-standard
|
||||
Linux/GNU interfaces. Move definitions of cpu_set_t to include/sys/types.h.
|
||||
Add prototypes for sched_setaffinity(), sched_getaffinity(),
|
||||
pthread_attr_setaffinity_np(), pthread_attr_getaffinity_np(),
|
||||
pthread_setaffinity_np(), and pthread_getaffinity_np(). No implementation
|
||||
is yet in place (2016-02-19).
|
||||
* sched/sched_cpuselect.c, include/nuttx/sched.h, and other files. Add
|
||||
a CPU affinity set to the TCB if SMP is enabled and use this CPU set as
|
||||
a mask for determining which CPUs the thread may run on (2016-02-19).
|
||||
* libc/pthread, sched/pthread/pthread_start.c, and include/pthread.h:
|
||||
Add an affinity field to the attrributes to permit controlling
|
||||
which CPUs a pthread may run on. Implements pthread_att_setaffinity_np()
|
||||
and pthread_attr_getaffinity_np() (2016-02-19).
|
||||
* sched/pthread: Add pthread_setaffinity() and pthread_getaffinity()
|
||||
(2016-02-19).
|
||||
* sched/sched: Add sched_setaffinity() and sched_getaffinity() (2016-02-19).
|
||||
* drivers/leds/rgbled.c: Add a driver to manage a RGB LED via PWM. From
|
||||
Alan Carvalho de Assis (2016-02-22).
|
||||
* arch/arm/src/stm32fcdiscovery: Add PWM support for the onboard RGB LED
|
||||
From Alan Carvalho de Assis (2016-02-22).
|
||||
* arch/arm/src/samv7: HSMCI driver can now be configured to handle unaligned
|
||||
data buffers (2016-02-22).
|
||||
* fs/fat: Add an option to force all transfers to be performed indirectly
|
||||
using the FAT file system's internal sector buffers (2016-02-22).
|
||||
* drivers/wireless/ieee802154: New directory. Nothing there yet (2016-02-25).
|
||||
* wireless/: New top level directory. Nothing there yet (2015-02-26).
|
||||
* wireless/ieee802154: Add an new directory to the build. Nothing there
|
||||
yet (2016-02-26).
|
||||
* include/nuttx/wireless/ieee802154: Add directory (and dummy header file)
|
||||
(2016-02-16).
|
||||
* arch/arm/include and src: Rename the imx directories to imx1 to make room
|
||||
in the namespace for other members of the i.MX family (2016-02-27).
|
||||
* arch/arm/include/imx6 and src/imx6: Evolving support for the NXP/Freescale
|
||||
i.MX6Q (2016-02-28).
|
||||
* configs/sabre-6quad: Placeholder that will eventually become board support
|
||||
for the NXP/Freescale Sabre 6Quad board (2016-02-28).
|
||||
* arch/arm/src/stm32: Support for STM32F46xx from Paul Alexander Patience
|
||||
* sched/semaphore/sem_reset.c and include/nuttx/semaphore.h: Add an internal,
|
||||
non-standard interface to reset a semaphore count. This is sometimes
|
||||
needed by drivers in order to recover from error conditions (2016-03-05)
|
||||
* AT24xx driver: Correct missing address calculation logic. From Frank
|
||||
Benkert (2016-03-08).
|
||||
* arch/ renaming: current_regs renamed to g_current_regs in all
|
||||
architectures. For ARM which is slowly developing SMP capability,
|
||||
g_current_regs is now an array of dimension 1 in most case but of higher
|
||||
dimension of the architecuture supports multiple CPUs (2016-03-09).
|
||||
* MTD: Increase block size in mtd_geometry_s to 32-bits (2016-03-09).
|
||||
* include/nuttx/clock.h: Missing parenteses in MSEC2TICK macro can
|
||||
cause wrong calculations. From Stefan Kolb (2016-03-09).
|
||||
* Build system: Added a 'make olddefconfig' target that will refresh
|
||||
a .config file without interaction. tools/refesh.sh no has a --silent
|
||||
option so that it can be used in batch modes without human input
|
||||
(2016-03-09).
|
||||
* tools/testbuild.sh: .config files were not being updated because (a)
|
||||
kconfig-conf was being called in the wrong directory and (b) apps/Kconfig
|
||||
had not yet been created. Now uses 'make olddefconfig' (2016-03-09).
|
||||
* arch/arm/src/stm32l4 and include/stm32l4: Add support for the STM32L4
|
||||
family. From Sebastien Lorquet (2016-03-10).
|
||||
* configs/nucleo-l476: Add support for the Nucleo-L476 board. From
|
||||
Sebastien Lorquet (2016-03-10).
|
||||
* sched/tls and include/nuttx/tls.h: Basic definitions needed to support
|
||||
thread local storage (TLS). Not used anywhere yet (and may not be used
|
||||
in the near future either) (2016-03-10).
|
||||
* sched/sched_note.c and include/nuttx/sched_note.c: Add a configuration
|
||||
option to buffer RTOS instrumentation data in an in-memory buffer
|
||||
(2016-03-17).
|
||||
* drivers/syslog/note_driver.c: Add a character driver that will allow
|
||||
an appliation to read buffered scheduler instrumentation data (2016-03-17).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# Directories.mk
|
||||
#
|
||||
# Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007-2012, 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -124,6 +124,12 @@ else
|
|||
OTHERDIRS += audio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DRIVERS_WIRELESS),y)
|
||||
NONFSDIRS += wireless
|
||||
else
|
||||
OTHERDIRS += wireless
|
||||
endif
|
||||
|
||||
# CLEANDIRS are the directories that will clean in. These are
|
||||
# all directories that we know about.
|
||||
# KERNDEPDIRS are the directories in which we will build target dependencies.
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 429e6427da4453da9342f52f57cf87bddafdb6e5
|
||||
Subproject commit 35343cbe6660bb07d9fee4c2e5af0dd450313c14
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# FlatLibs.mk
|
||||
#
|
||||
# Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007-2012, 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -109,6 +109,12 @@ ifeq ($(CONFIG_AUDIO),y)
|
|||
NUTTXLIBS += lib$(DELIM)libaudio$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Add libraries for the Wireless sub-system
|
||||
|
||||
ifeq ($(CONFIG_WIRELESS),y)
|
||||
NUTTXLIBS += lib$(DELIM)libwireless$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Export all libraries
|
||||
|
||||
EXPORTLIBS = $(NUTTXLIBS)
|
||||
|
|
|
|||
33
Kconfig
33
Kconfig
|
|
@ -165,7 +165,7 @@ config BUILD_PROTECTED
|
|||
|
||||
config BUILD_KERNEL
|
||||
bool "NuttX kernel build"
|
||||
depends on ARCH_USE_MMU && ARCH_ADDRENV && EXPERIMENTAL
|
||||
depends on ARCH_USE_MMU && ARCH_ADDRENV
|
||||
select LIB_SYSCALL
|
||||
---help---
|
||||
Builds NuttX as a separately compiled kernel. No applications are
|
||||
|
|
@ -376,6 +376,12 @@ config ARCH_STDARG_H
|
|||
ARCH_STDARG_H=y and providing. If ARCH_STDARG_H, is not defined, then
|
||||
the stdarg.h header file will stay out-of-the-way in include/nuttx/.
|
||||
|
||||
config ARCH_DEBUG_H
|
||||
bool "debug.h"
|
||||
default n
|
||||
---help---
|
||||
The debug.h contains architecture dependent debugging primitives
|
||||
|
||||
endmenu # Customize Header Files
|
||||
|
||||
menu "Debug Options"
|
||||
|
|
@ -412,6 +418,7 @@ comment "Subsystem Debug Options"
|
|||
config DEBUG_AUDIO
|
||||
bool "Audio Device Debug Output"
|
||||
default n
|
||||
depends on AUDIO
|
||||
---help---
|
||||
Enable low level debug SYSLOG output from the audio subsystem and
|
||||
device drivers. (disabled by default). Support for this debug option
|
||||
|
|
@ -420,6 +427,7 @@ config DEBUG_AUDIO
|
|||
config DEBUG_BINFMT
|
||||
bool "Binary Loader Debug Output"
|
||||
default n
|
||||
depends on !BINFMT_DISABLE
|
||||
---help---
|
||||
Enable binary loader debug SYSLOG output (disabled by default)
|
||||
|
||||
|
|
@ -482,6 +490,15 @@ config DEBUG_SYSCALL
|
|||
Enable very low level output related to system calls. This gives
|
||||
you basically a poor man's version of strace.
|
||||
|
||||
config DEBUG_WIRELESS
|
||||
bool "Wireless Device Debug Output"
|
||||
default n
|
||||
depends on WIRELESS
|
||||
---help---
|
||||
Enable low level debug SYSLOG output from the wireless subsystem and
|
||||
device drivers. (disabled by default). Support for this debug option
|
||||
is architecture-specific and may not be available for some MCUs.
|
||||
|
||||
comment "OS Function Debug Options"
|
||||
|
||||
config DEBUG_DMA
|
||||
|
|
@ -548,6 +565,16 @@ config DEBUG_INPUT
|
|||
this debug option is board-specific and may not be available for
|
||||
some boards.
|
||||
|
||||
config DEBUG_DISCRETE
|
||||
bool "Discrete I/O Debug Output"
|
||||
default n
|
||||
depends on DISCRETE_IO
|
||||
---help---
|
||||
Enable low level debug SYSLOG output from the discrete I/O device
|
||||
drivers such as LEDs and I/O expanders (disabled by default).
|
||||
Support for this debug option is board-specific and may not be
|
||||
available for some boards.
|
||||
|
||||
config DEBUG_ANALOG
|
||||
bool "Analog Device Debug Output"
|
||||
default n
|
||||
|
|
@ -766,6 +793,10 @@ menu "Audio Support"
|
|||
source audio/Kconfig
|
||||
endmenu
|
||||
|
||||
menu "Wireless Support"
|
||||
source wireless/Kconfig
|
||||
endmenu
|
||||
|
||||
menu "Binary Loader"
|
||||
source binfmt/Kconfig
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# KernalLibs.mk
|
||||
#
|
||||
# Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -104,6 +104,12 @@ ifeq ($(CONFIG_AUDIO),y)
|
|||
NUTTXLIBS += lib$(DELIM)libaudio$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Add libraries for the Wireless sub-system
|
||||
|
||||
ifeq ($(CONFIG_WIRELESS),y)
|
||||
NUTTXLIBS += lib$(DELIM)libwireless$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Export only the user libraries
|
||||
|
||||
EXPORTLIBS = $(USERLIBS)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ $(ARCH_SRC)$(DELIM)libkarch$(LIBEXT): context
|
|||
lib$(DELIM)libkarch$(LIBEXT): $(ARCH_SRC)$(DELIM)libkarch$(LIBEXT)
|
||||
$(Q) install $(ARCH_SRC)$(DELIM)libkarch$(LIBEXT) lib$(DELIM)libkarch$(LIBEXT)
|
||||
|
||||
|
||||
sched$(DELIM)libsched$(LIBEXT): context
|
||||
$(Q) $(MAKE) -C sched TOPDIR="$(TOPDIR)" libsched$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE)
|
||||
|
||||
|
|
@ -119,6 +118,18 @@ audio$(DELIM)libaudio$(LIBEXT): context
|
|||
lib$(DELIM)libaudio$(LIBEXT): audio$(DELIM)libaudio$(LIBEXT)
|
||||
$(Q) install audio$(DELIM)libaudio$(LIBEXT) lib$(DELIM)libaudio$(LIBEXT)
|
||||
|
||||
wireless$(DELIM)libwireless$(LIBEXT): context
|
||||
$(Q) $(MAKE) -C wireless TOPDIR="$(TOPDIR)" libwireless$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE)
|
||||
|
||||
lib$(DELIM)libwireless$(LIBEXT): wireless$(DELIM)libwireless$(LIBEXT)
|
||||
$(Q) install wireless$(DELIM)libwireless$(LIBEXT) lib$(DELIM)libwireless$(LIBEXT)
|
||||
|
||||
$(ARCH_SRC)$(DELIM)libarch$(LIBEXT): context
|
||||
$(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" libarch$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE)
|
||||
|
||||
lib$(DELIM)libarch$(LIBEXT): $(ARCH_SRC)$(DELIM)libarch$(LIBEXT)
|
||||
$(Q) install $(ARCH_SRC)$(DELIM)libarch$(LIBEXT) lib$(DELIM)libarch$(LIBEXT)
|
||||
|
||||
# Special case
|
||||
|
||||
syscall$(DELIM)libstubs$(LIBEXT): context
|
||||
|
|
@ -190,9 +201,3 @@ mm$(DELIM)libmm$(LIBEXT): context
|
|||
|
||||
lib$(DELIM)libmm$(LIBEXT): mm$(DELIM)libmm$(LIBEXT)
|
||||
$(Q) install mm$(DELIM)libmm$(LIBEXT) lib$(DELIM)libmm$(LIBEXT)
|
||||
|
||||
$(ARCH_SRC)$(DELIM)libarch$(LIBEXT): context
|
||||
$(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" libarch$(LIBEXT)
|
||||
|
||||
lib$(DELIM)libarch$(LIBEXT): $(ARCH_SRC)$(DELIM)libarch$(LIBEXT)
|
||||
$(Q) install $(ARCH_SRC)$(DELIM)libarch$(LIBEXT) lib$(DELIM)libarch$(LIBEXT)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# Makefile.unix
|
||||
#
|
||||
# Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007-2012, 2014-2015 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -72,9 +72,13 @@ ARCH_SRC = $(ARCH_DIR)/src
|
|||
ARCH_INC = $(ARCH_DIR)/include
|
||||
|
||||
ifeq ($(CONFIG_ARCH_BOARD_CUSTOM),y)
|
||||
BOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
ifeq ($(CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH),y)
|
||||
BOARD_DIR = $(TOPDIR)$(DELIM)$(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
else
|
||||
BOARD_DIR = $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)
|
||||
BOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
endif
|
||||
else
|
||||
BOARD_DIR = $(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)
|
||||
endif
|
||||
|
||||
# CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file.
|
||||
|
|
@ -265,7 +269,10 @@ include/nuttx/config.h: $(TOPDIR)/.config tools/mkconfig$(HOSTEXEEXT)
|
|||
# Targets used to create dependencies
|
||||
|
||||
tools/mkdeps$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" mkdeps$(HOSTEXEEXT)
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" mkdeps$(HOSTEXEEXT)
|
||||
|
||||
tools/cnvwindeps$(HOSTEXEEXT):
|
||||
$(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" cnvwindeps$(HOSTEXEEXT)
|
||||
|
||||
# dirlinks, and helpers
|
||||
#
|
||||
|
|
@ -456,12 +463,12 @@ download: $(BIN)
|
|||
# pass1dep: Create pass1 build dependencies
|
||||
# pass2dep: Create pass2 build dependencies
|
||||
|
||||
pass1dep: context tools/mkdeps$(HOSTEXEEXT)
|
||||
pass1dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
|
||||
$(Q) for dir in $(USERDEPDIRS) ; do \
|
||||
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \
|
||||
done
|
||||
|
||||
pass2dep: context tools/mkdeps$(HOSTEXEEXT)
|
||||
pass2dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
|
||||
$(Q) for dir in $(KERNDEPDIRS) ; do \
|
||||
$(MAKE) -C $$dir TOPDIR="$(TOPDIR)" EXTRADEFINES=$(KDEFINE) depend; \
|
||||
done
|
||||
|
|
@ -473,19 +480,22 @@ pass2dep: context tools/mkdeps$(HOSTEXEEXT)
|
|||
# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See
|
||||
# README.txt file in the NuttX tools GIT repository for additional information.
|
||||
|
||||
config:
|
||||
config: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf Kconfig
|
||||
|
||||
oldconfig:
|
||||
oldconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfig
|
||||
|
||||
menuconfig:
|
||||
olddefconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --olddefconfig Kconfig
|
||||
|
||||
menuconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfig
|
||||
|
||||
qconfig:
|
||||
qconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-qconf Kconfig
|
||||
|
||||
gconfig:
|
||||
gconfig: apps_preconfig
|
||||
$(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-gconf Kconfig
|
||||
|
||||
# export
|
||||
|
|
@ -556,11 +566,17 @@ endif
|
|||
# as a convenience, the following targets are included to support housekeeping
|
||||
# functions in the user application directory from the NuttX build directory.
|
||||
#
|
||||
# apps_preconfig: Prepare applications to be configured
|
||||
# apps_clean: Perform the clean operation only in the user application
|
||||
# directory
|
||||
# apps_distclean: Perform the distclean operation only in the user application
|
||||
# directory.
|
||||
|
||||
apps_preconfig:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" preconfig
|
||||
endif
|
||||
|
||||
apps_clean:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" clean
|
||||
|
|
|
|||
25
Makefile.win
25
Makefile.win
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# Makefile.win
|
||||
#
|
||||
# Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2012, 2015 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -65,9 +65,13 @@ ARCH_SRC = $(ARCH_DIR)\src
|
|||
ARCH_INC = $(ARCH_DIR)\include
|
||||
|
||||
ifeq ($(CONFIG_ARCH_BOARD_CUSTOM),y)
|
||||
BOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
ifeq ($(CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH),y)
|
||||
BOARD_DIR = $(TOPDIR)$(DELIM)$(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
else
|
||||
BOARD_DIR = $(TOPDIR)${DELIM}configs$(DELIM)$(CONFIG_ARCH_BOARD)
|
||||
BOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)
|
||||
endif
|
||||
else
|
||||
BOARD_DIR = $(TOPDIR)$(DELIM)configs$(DELIM)$(CONFIG_ARCH_BOARD)
|
||||
endif
|
||||
|
||||
# CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file.
|
||||
|
|
@ -476,13 +480,16 @@ pass2dep: context tools\mkdeps$(HOSTEXEEXT)
|
|||
# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See
|
||||
# misc\tools\README.txt for additional information.
|
||||
|
||||
config:
|
||||
config: apps_preconfig
|
||||
$(Q) set APPSDIR=$(patsubst "%",%,${CONFIG_APPS_DIR})& kconfig-conf Kconfig
|
||||
|
||||
oldconfig:
|
||||
oldconfig: apps_preconfig
|
||||
$(Q) set APPSDIR=$(patsubst "%",%,${CONFIG_APPS_DIR})& kconfig-conf --oldconfig Kconfig
|
||||
|
||||
menuconfig: configenv
|
||||
olddefconfig: apps_preconfig
|
||||
$(Q) set APPSDIR=$(patsubst "%",%,${CONFIG_APPS_DIR})& kconfig-conf --olddefconfig Kconfig
|
||||
|
||||
menuconfig: configenv apps_preconfig
|
||||
$(Q) set APPSDIR=$(patsubst "%",%,${CONFIG_APPS_DIR})& kconfig-mconf Kconfig
|
||||
|
||||
# export
|
||||
|
|
@ -545,11 +552,17 @@ endif
|
|||
# as a convenience, the following targets are included to support housekeeping
|
||||
# functions in the user application directory from the NuttX build directory.
|
||||
#
|
||||
# apps_preconfig: Prepare applications to be configured
|
||||
# apps_clean: Perform the clean operation only in the user application
|
||||
# directory
|
||||
# apps_distclean: Perform the distclean operation only in the user application
|
||||
# directory.
|
||||
|
||||
apps_preconfig:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C "$(APPDIR)" TOPDIR="$(TOPDIR)" preconfig
|
||||
endif
|
||||
|
||||
apps_clean:
|
||||
ifneq ($(APPDIR),)
|
||||
$(Q) $(MAKE) -C "$(APPDIR)" TOPDIR="$(TOPDIR)" clean
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# ProtectedLibs.mk
|
||||
#
|
||||
# Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007-2012, 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -114,6 +114,12 @@ ifeq ($(CONFIG_AUDIO),y)
|
|||
NUTTXLIBS += lib$(DELIM)libaudio$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Add libraries for the Wireless sub-system
|
||||
|
||||
ifeq ($(CONFIG_WIRELESS),y)
|
||||
NUTTXLIBS += lib$(DELIM)libwireless$(LIBEXT)
|
||||
endif
|
||||
|
||||
# Export only the user libraries
|
||||
|
||||
EXPORTLIBS = $(USERLIBS)
|
||||
|
|
|
|||
50
README.txt
50
README.txt
|
|
@ -79,6 +79,10 @@ Installing Cygwin
|
|||
the answer to that and so will continue to recommend installing
|
||||
EVERYTHING.
|
||||
|
||||
You should certainly be able to omit "Science", "Math", and
|
||||
"Publishing". You can try omitting KDE, Gnome, GTK, and other
|
||||
graphics packages if you don't plan to use them.
|
||||
|
||||
After installing Cygwin, you will get lots of links for installed
|
||||
tools and shells. I use the RXVT native shell. It is fast and reliable
|
||||
and does not require you to run the Cygwin X server (which is neither
|
||||
|
|
@ -472,6 +476,16 @@ Refreshing Configurations
|
|||
be? Enter ? in response to the 'make oldconfig' prompt and it will show
|
||||
you the help text that goes with the option.
|
||||
|
||||
If you don't want to make any decisions are are willing to just accep the
|
||||
recommended default value for each new configuration item, an even easier
|
||||
way is:
|
||||
|
||||
make oldefconfig
|
||||
|
||||
The olddefconfig target will simply bring you configuration up to date with
|
||||
the current Kconfig files, setting any new options to the default value.
|
||||
No questions asked.
|
||||
|
||||
NuttX Configuration Tool
|
||||
------------------------
|
||||
|
||||
|
|
@ -1107,17 +1121,6 @@ Window Native Toolchain Issues
|
|||
is not a long as you might think because there is no dependency checking
|
||||
if you are using a native Windows toolchain. That bring us to #3:
|
||||
|
||||
3. Dependencies are not made when using Windows versions of the GCC on a POSIX
|
||||
platform (i.e., Cygwin). This is because the dependencies are generated
|
||||
using Windows paths which do not work with the Cygwin make.
|
||||
|
||||
MKDEP = $(TOPDIR)/tools/mknulldeps.sh
|
||||
|
||||
If you are building natively on Windows, then no such conflict exists
|
||||
and the best selection is:
|
||||
|
||||
MKDEP = $(TOPDIR)/tools/mkdeps.exe
|
||||
|
||||
General Pre-built Toolchain Issues
|
||||
|
||||
To continue with the list of "Window Native Toolchain Issues" we can add
|
||||
|
|
@ -1251,6 +1254,8 @@ nuttx/
|
|||
|- configs/
|
||||
| |- amber/
|
||||
| | `- README.txt
|
||||
| |- arduino-mega2560/
|
||||
| | `- README.txt
|
||||
| |- arduino-due/
|
||||
| | `- README.txt
|
||||
| |- avr32dev1/
|
||||
|
|
@ -1304,6 +1309,8 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- kwikstik-k40/
|
||||
| | `- README.txt
|
||||
| |- launchxl-tms57004/
|
||||
| | `- README.txt
|
||||
| |- lincoln60/
|
||||
| | `- README.txt
|
||||
| |- lm3s6432-s2e/
|
||||
|
|
@ -1314,8 +1321,12 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- lpc4330-xplorer/
|
||||
| | `- README.txt
|
||||
| |- lpc4337-ws/
|
||||
| | `- README.txt
|
||||
| |- lpc4357-evb/
|
||||
| | `- README.txt
|
||||
| |- lpc4370-link2/
|
||||
| | `- README.txt
|
||||
| |- lpcxpresso-lpc1115/
|
||||
| | `- README.txt
|
||||
| |- lpcxpresso-lpc1768/
|
||||
|
|
@ -1359,6 +1370,8 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- olimex-stm32-h405/
|
||||
| | `- README.txt
|
||||
| |- olimex-stm32-h407/
|
||||
| | `- README.txt
|
||||
| |- olimex-stm32-p107/
|
||||
| | `- README.txt
|
||||
| |- olimex-stm32-p207/
|
||||
|
|
@ -1385,6 +1398,10 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- rgmp/
|
||||
| | `- README.txt
|
||||
| |- sabre-6quad/
|
||||
| | `- README.txt
|
||||
| |- sama5d2-xult/
|
||||
| | `- README.txt
|
||||
| |- sama5d3x-ek/
|
||||
| | `- README.txt
|
||||
| |- sama5d3-xplained/
|
||||
|
|
@ -1407,9 +1424,12 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- sam4s-xplained-pro/
|
||||
| | `- README.txt
|
||||
| |- samv7i-xult/
|
||||
| |- same70-xplained/
|
||||
| | `- README.txt
|
||||
| |- samv71-xult/
|
||||
| | `- README.txt
|
||||
| |- sim/
|
||||
| | |- include/README.txt
|
||||
| | `- README.txt
|
||||
| |- shenzhou/
|
||||
| | `- README.txt
|
||||
|
|
@ -1453,6 +1473,8 @@ nuttx/
|
|||
| | `- README.txt
|
||||
| |- twr-k60n512/
|
||||
| | `- README.txt
|
||||
| |- u-blox-co27/
|
||||
| | `- README.txt
|
||||
| |- ubw32/
|
||||
| | `- README.txt
|
||||
| |- us7032evb1/
|
||||
|
|
@ -1538,6 +1560,8 @@ apps/
|
|||
| |- json/README.txt
|
||||
| |- pashello/README.txt
|
||||
| `- README.txt
|
||||
|- gpsutils/
|
||||
| `- minmea/README.txt
|
||||
|- graphics/
|
||||
| `- tiff/README.txt
|
||||
|- interpreters/
|
||||
|
|
@ -1573,6 +1597,8 @@ apps/
|
|||
| | `- README.txt
|
||||
| |- nxplayer
|
||||
| | `- README.txt
|
||||
| |- symtab/
|
||||
| | `- README.txt
|
||||
| |- usbmsc
|
||||
| | `- README.txt
|
||||
| |- zmodem
|
||||
|
|
|
|||
1210
ReleaseNotes
1210
ReleaseNotes
File diff suppressed because it is too large
Load diff
270
TODO
270
TODO
|
|
@ -1,4 +1,5 @@
|
|||
NuttX TODO List (Last updated August 6, 2015)
|
||||
NuttX TODO List (Last updated February 18, 2016)
|
||||
NuttX TODO List (Last updated February 18, 2016)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This file summarizes known NuttX bugs, limitations, inconsistencies with
|
||||
|
|
@ -9,27 +10,29 @@ issues reated to each board port.
|
|||
|
||||
nuttx/
|
||||
|
||||
(12) Task/Scheduler (sched/)
|
||||
(13) Task/Scheduler (sched/)
|
||||
(1) Memory Management (mm/)
|
||||
(3) Signals (sched/signal, arch/)
|
||||
(2) pthreads (sched/pthread)
|
||||
(0) Message Queues (sched/mqueue)
|
||||
(4) C++ Support
|
||||
(6) Kernel/Protected Build
|
||||
(3) C++ Support
|
||||
(6) Binary loaders (binfmt/)
|
||||
(12) Network (net/, drivers/net)
|
||||
(4) USB (drivers/usbdev, drivers/usbhost)
|
||||
(12) Libraries (libc/, libm/)
|
||||
(0) Other drivers (drivers/)
|
||||
(11) Libraries (libc/, libm/)
|
||||
(11) File system/Generic drivers (fs/, drivers/)
|
||||
(8) Graphics subsystem (graphics/)
|
||||
(1) Pascal add-on (pcode/)
|
||||
(2) Build system / Toolchains
|
||||
(3) Linux/Cywgin simulation (arch/sim)
|
||||
(5) ARM (arch/arm/)
|
||||
(1) Build system / Toolchains
|
||||
(4) Linux/Cywgin simulation (arch/sim)
|
||||
(4) ARM (arch/arm/)
|
||||
|
||||
apps/
|
||||
|
||||
(4) Network Utilities (apps/netutils/)
|
||||
(3) NuttShell (NSH) (apps/nshlib)
|
||||
(3) Network Utilities (apps/netutils/)
|
||||
(2) NuttShell (NSH) (apps/nshlib)
|
||||
(1) System libraries apps/system (apps/system)
|
||||
(4) Other Applications & Tests (apps/examples/)
|
||||
|
||||
|
|
@ -213,6 +216,27 @@ o Task/Scheduler (sched/)
|
|||
Status: Open
|
||||
Priority: Medium-ish
|
||||
|
||||
Title: SCALABILITY
|
||||
Description: Task control information is retained in simple lists. This
|
||||
is completely appropriate for small embedded systems where
|
||||
the number of tasks, N, is relatively small. Most list
|
||||
operations are O(N). This could become as issue if N gets
|
||||
very large.
|
||||
|
||||
In that case, these simple lists should be replaced with
|
||||
something more performant such as a balanced tree in the
|
||||
case of ordered lists. Fortunately, most internal lists are
|
||||
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
|
||||
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/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -314,9 +338,17 @@ o Signals (sched/signal, arch/)
|
|||
embedded system.
|
||||
|
||||
Title: SIGEV_THREAD
|
||||
Description: sig_notify() logic does not support SIGEV_THREAD; structure
|
||||
struct sigevent does not provide required members sigev_notify_function
|
||||
or sigev_notify_attributes.
|
||||
Description: Implementation of support for support for SIGEV_THREAD is available
|
||||
only in the FLAT build mode because it uses the OS work queues to
|
||||
perform the callback. The alternative for the PROTECTED and KERNEL
|
||||
builds would be to create pthreads in the user space to perform the
|
||||
callbacks. That is not a very attractive solution due to performance
|
||||
issues. It would also require some additional logic to specify the
|
||||
TCB of the parent so that the pthread could be bound to the correct
|
||||
group.
|
||||
|
||||
There is also some user-space logic in libc/aio/lio_listio.c. That
|
||||
logic could use the user-space work queue for the callbacks.
|
||||
Status: Low, there are alternative designs. However, these features
|
||||
are required by the POSIX standard.
|
||||
Priority: Low for now
|
||||
|
|
@ -414,36 +446,20 @@ o Kernel/Protected Build
|
|||
|
||||
COMMAND KERNEL INTERFACE(s)
|
||||
-------- ----------------------------------------------
|
||||
losetup losetup(), loteardown()
|
||||
mkfatfs mkfatfs
|
||||
mkrd ramdisk_register()
|
||||
dd bchlib_setup(), bchlib_read(), bchlib_write(),
|
||||
bchlib_teardown()
|
||||
ps sched_foreach()
|
||||
ifup netdev_foreach()
|
||||
ifdown netdev_foreach()
|
||||
ifconfig netdev_foreach(), g_netstats
|
||||
ping icmp_ping()
|
||||
|
||||
The busybox mkfatfs does not involve any OS calls; it does
|
||||
its job by simply opening the block driver (using open/xopen)
|
||||
and modifying it with write operations. See:
|
||||
|
||||
http://git.busybox.net/busybox/tree/util-linux/mkfs_vfat.c
|
||||
|
||||
Status: Open
|
||||
Priority: Medium/High -- the kernel build configuration is not fully fielded
|
||||
yet.
|
||||
|
||||
Title: NSH free COMMAND LIMITATION
|
||||
Description: The NSH 'free' command only shows memory usage in the user
|
||||
heap only, not usage in the kernel heap. I am thinking that
|
||||
kernel heap memory usage should be available in /proc/memory.
|
||||
Status: Open
|
||||
Priority: Medium/High
|
||||
|
||||
Title: TELNETD PARTITIONING.
|
||||
Description: Telnetd is implemented as a driver that resides in the apps/
|
||||
directory. In the kernel/protected build modes, the driver
|
||||
logic must be moved into the kernel part of the build (nuttx/,
|
||||
although the application level interfaces must stay in apps/).
|
||||
Status: Open
|
||||
Priority: Medium
|
||||
|
||||
Title: NxTERM PARTITIONING.
|
||||
Description: NxTerm is implemented (correctly) as a driver that resides
|
||||
in the nuttx/ directory. However, the user interfaces must be
|
||||
|
|
@ -508,6 +524,10 @@ o Kernel/Protected Build
|
|||
console output. The requests for the pid() are part of the
|
||||
implementation of the I/O's re-entrant semaphore implementation and
|
||||
would not be an issue in the more general case.
|
||||
|
||||
Update:
|
||||
One solution might be to used CONFIG_TLS, add the PID to struct
|
||||
tls_info_s. Then the PID could be obtained without a system call.
|
||||
Status: Open
|
||||
Priority: Low-Medium. Right now, I do not know if these syscalls are a
|
||||
real performance issue or not. The above statistics were collected
|
||||
|
|
@ -563,20 +583,6 @@ o C++ Support
|
|||
would be to get a hold of the compilers definition of size_t.
|
||||
Priority: Low.
|
||||
|
||||
Title: STATIC CONSTRUCTORS
|
||||
Description: Need to call static constructors
|
||||
Update: Static constructors are implemented for the STM32 F4 and
|
||||
this will provide the model for all solutions. Basically, if
|
||||
CONFIG_HAVE_CXXINITIALIZE=y is defined in the configuration, then
|
||||
board-specific code must provide the interface up_cxxinitialize().
|
||||
up_cxxinitialize() is called from application logic to initialize
|
||||
all static class instances. This TODO item probably has to stay
|
||||
open because this solution is only available on STM32 F4.
|
||||
Status: Open
|
||||
Priority: Low, depends on toolchain. Call to gcc's built-in static
|
||||
constructor logic will probably have to be performed by
|
||||
user logic in the application.
|
||||
|
||||
Title: STATIC CONSTRUCTORS AND MULTITASKING
|
||||
Description: The logic that calls static constructors operates on the main
|
||||
thread of the initial user application task. Any static
|
||||
|
|
@ -801,25 +807,6 @@ o Network (net/, drivers/net)
|
|||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
Title: STANDARDIZE ETHERNET DRIVER STATISTICS
|
||||
Description: Need to standardize collection of statistics from network
|
||||
drivers. Currently they are useless because they are not
|
||||
accessible. The solution is to standardize the structure
|
||||
that holds the drivers statistics. Then apps/nshlib
|
||||
ifconfig command could present the driver statistics.
|
||||
|
||||
Currently these drivers support non-standard statistics:
|
||||
|
||||
arch/arm/src/kinetis/kinetis_enet.c
|
||||
arch/arm/src/lpc17xx/lpc17_ethernet.c
|
||||
arch/arm/src/tiva/lm3s_ethernet.c
|
||||
arch/mips/src/pic32mx/pic32mx-ethernet.c
|
||||
arch/z80/src/ez80/ez80_emac.c
|
||||
|
||||
The other Ethernet drivers support no statistics.
|
||||
Status: Open
|
||||
Priority: Low. This is not a bug but an enhancement idea.
|
||||
|
||||
Title: CONCURRENT TCP SEND OPERATIONS
|
||||
Description: At present, there cannot be two concurrent active TCP send
|
||||
operations in progress using the same socket. This is because
|
||||
|
|
@ -990,6 +977,12 @@ o Network (net/, drivers/net)
|
|||
Priority: Low. I don't know of any issues now, but I am sure that
|
||||
someone will encounter this in the future.
|
||||
|
||||
Title: MISSING netdb INTERFACES
|
||||
Description: There is no implementation for many netdb interfaces such as
|
||||
getaddrinfo(), freeaddrinfo(), getnameinfo(), etc.
|
||||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
o USB (drivers/usbdev, drivers/usbhost)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -1197,11 +1190,6 @@ o Libraries (libc/)
|
|||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
Title: DAYS OF THE WEEK
|
||||
Description: strftime() and other timing functions do not handle days of the week.
|
||||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
Title: RESETTING GETOPT()
|
||||
Description: There is an issue with the way that getopt() handles errors that
|
||||
return '?'.
|
||||
|
|
@ -1293,12 +1281,16 @@ o Libraries (libc/)
|
|||
it does not return at all as the loop in it does not
|
||||
converge, hanging your app.
|
||||
|
||||
"There are likely many other issues like these as the Rhombs
|
||||
"There are likely many other issues like these as the Rhombus
|
||||
OS code has not been tested or used that much. Sorry for not
|
||||
providing patches, but we found it easier just to switch the
|
||||
math library."
|
||||
|
||||
Ref: https://groups.yahoo.com/neo/groups/nuttx/conversations/messages/7805
|
||||
|
||||
UPDATE: 2015-09-01: A fix for the noted problems with asin()
|
||||
has been applied.
|
||||
|
||||
Status: Open
|
||||
Priority: Low for casual users but clearly high if you need care about
|
||||
these incorrect corner case behaviors in the math libraries.
|
||||
|
|
@ -1308,8 +1300,8 @@ o File system / Generic drivers (fs/, drivers/)
|
|||
|
||||
NOTE: The NXFFS file system has its own TODO list at nuttx/fs/nxffs/README.txt
|
||||
|
||||
Title: CHMOD() AND TRUNCATE()
|
||||
Description: Implement chmod(), truncate().
|
||||
Title: CHMOD(), TRUNCATE(), AND FSTAT()
|
||||
Description: Implement chmod(), truncate(), and fstat().
|
||||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
|
|
@ -1545,6 +1537,7 @@ o Graphics subsystem (graphics/)
|
|||
Status: Open
|
||||
Priority: Low, not a serious issue but worth noting. There is no plan
|
||||
to change this behavior.
|
||||
|
||||
o Pascal Add-On (pcode/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -1568,16 +1561,6 @@ o Pascal Add-On (pcode/)
|
|||
o Build system
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Title: WINDOWS DEPENDENCY GENERATION
|
||||
Description: Dependency generation is currently disabled when a Windows native
|
||||
toolchain is used in a POSIX-like environment (like Cygwin). The
|
||||
issue is that the Windows tool generates dependencies use Windows
|
||||
path formatting and this fails with the dependency file (Make.dep)
|
||||
is include). Perhaps the only issue is that all of the Windows
|
||||
dependencies needed to be quoted in the Make.dep files.
|
||||
Status: Open
|
||||
Priority: Low -- unless some dependency-related build issues is discovered.
|
||||
|
||||
Title: MAKE EXPORT LIMITATIONS
|
||||
Description: The top-level Makefile 'export' target that will bundle up all of the
|
||||
NuttX libraries, header files, and the startup object into an export-able
|
||||
|
|
@ -1591,6 +1574,9 @@ o Build system
|
|||
Status: Open
|
||||
Priority: Low.
|
||||
|
||||
o Other drivers (drivers/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
o Linux/Cywgin simulation (arch/sim)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -1623,18 +1609,81 @@ o Linux/Cywgin simulation (arch/sim)
|
|||
"faked" during IDLE loop processing and, as a result, there is no
|
||||
task pre-emption because there are no asynchronous events. This could
|
||||
probably be fixed if the "timer interrupt" were driver by Linux
|
||||
signals. NOTE: You would also have to implement irqsave() and
|
||||
irqrestore() to block and (conditionally) unblock the signal.
|
||||
signals. NOTE: You would also have to implement up_irq_save() and
|
||||
up_irq_restore() to block and (conditionally) unblock the signal.
|
||||
Status: Open
|
||||
Priority: Low
|
||||
|
||||
Title: SMP SIMULATION ISSUES
|
||||
Description: The configuration has basic support SMP testing. The simulation
|
||||
supports the emulation of multiple CPUs by creating multiple
|
||||
pthreads, each run a copy of the simulation in the same process
|
||||
address space.
|
||||
|
||||
At present, the SMP simulation is not fully functional: It does
|
||||
operate on the simulated CPU threads for a few context switches
|
||||
then fails during a setjmp() operation. I suspect that this is
|
||||
not an issue with the NuttX SMP logic but more likely some chaos
|
||||
in the pthread controls. I have seen similar such strange behavior
|
||||
other times that I have tried to use setjmp/longmp from a signal
|
||||
handler! Like when I tried to implement simulated interrupts
|
||||
using signals.
|
||||
|
||||
Apparently, if longjmp is invoked from the context of a signal
|
||||
handler, the result is undefined:
|
||||
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1318.htm
|
||||
|
||||
You can enable SMP for ostest configuration by enabling:
|
||||
|
||||
-# CONFIG_EXPERIMENTAL is not set
|
||||
+CONFIG_EXPERIMENTAL=y
|
||||
|
||||
+CONFIG_SPINLOCK=y
|
||||
+CONFIG_SMP=y
|
||||
+CONFIG_SMP_NCPUS=2
|
||||
+CONFIG_SMP_IDLETHREAD_STACKSIZE=2048
|
||||
|
||||
You also must enable near-realtime-performance otherwise even long
|
||||
timeouts will expire before a CPU thread even has a chance to
|
||||
execute.
|
||||
|
||||
-# CONFIG_SIM_WALLTIME is not set
|
||||
+CONFIG_SIM_WALLTIME=y
|
||||
|
||||
And you can enable some additional debug output with:
|
||||
|
||||
-# CONFIG_DEBUG_SCHED is not set
|
||||
+CONFIG_DEBUG_SCHED=y
|
||||
|
||||
-# CONFIG_SCHED_INSTRUMENTATION is not set
|
||||
+CONFIG_SCHED_INSTRUMENTATION=y
|
||||
|
||||
The NSH configuration can also be forced to run SMP, but
|
||||
suffers from the same quirky behavior. I can be made
|
||||
reliable if you modify arch/sim/src/up_idle.c so that
|
||||
the IDLE loop only runs for CPU0. Otherwise, often
|
||||
simuart_post() will be called from CPU1 and it will try
|
||||
to restart NSH on CPU0 and, again, the same quirkiness
|
||||
occurs.
|
||||
|
||||
But for example, this command:
|
||||
|
||||
nsh> sleep 1 &
|
||||
|
||||
will execute the sleep command on CPU1 which has worked
|
||||
every time that I have tried it (which is not too many
|
||||
times).
|
||||
|
||||
Status: Open
|
||||
Priority: Low, SMP is important, but SMP on the simulator is not
|
||||
|
||||
o ARM (arch/arm/)
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Title: IMPROVED ARM INTERRUPT HANDLING
|
||||
Description: ARM interrupt handling performance could be improved in some
|
||||
ways. One easy way is to use a pointer to the context save
|
||||
area in current_regs instead of using up_copystate so much.
|
||||
area in g_current_regs instead of using up_copystate so much.
|
||||
|
||||
This approach is already implemented for the ARM Cortex-M0,
|
||||
Cortex-M3, Cortex-M4, and Cortex-A5 families. But still needs
|
||||
|
|
@ -1694,31 +1743,6 @@ o ARM (arch/arm/)
|
|||
If your design needs continuous interrupts like this, please try
|
||||
the above change and, please, submit a patch with the working fix.
|
||||
|
||||
Title: STACK ALIGNMENT IN INTERRUPT HANDLERS
|
||||
Description: The EABI standard requires that the stack always have a 32-byte
|
||||
alignment. There is no guarantee at present that the stack will be
|
||||
so aligned in an interrupt handler. Therefore, I would expect some
|
||||
issues if, for example, floating point or perhaps long long operations
|
||||
were performed in an interrupt handler.
|
||||
|
||||
This issue exists for ARM7, ARM9, Cortex-M0, Cortex-M3, and
|
||||
Cortex-M4 but has been addressed for the Cortex-A5. The fix
|
||||
is really simple can cannot be incorporated without some
|
||||
substantial testing. For ARM, the fix is the following logic
|
||||
arround each call into C code from assembly:
|
||||
|
||||
mov r4, sp /* Save the SP in a preserved register */
|
||||
bic sp, sp, #7 /* Force 8-byte alignment */
|
||||
bl cfunction /* Call the C function */
|
||||
mov sp, r4 /* Restore the possibly unaligned stack pointer */
|
||||
|
||||
This same issue applies to the interrupt stack which is, I think
|
||||
improperly aligned in almost all cases (except Cortex-A5).
|
||||
|
||||
Status: Open
|
||||
Priority: Low for me because I never do floating point operations in
|
||||
interrupt handlers.
|
||||
|
||||
Title: IMPROVED TASK START-UP AND SYSCALL RETURN
|
||||
Description: Couldn't up_start_task and up_start_pthread syscalls be
|
||||
eliminated. Wouldn't this work to get us from kernel-
|
||||
|
|
@ -1758,18 +1782,6 @@ o Network Utilities (apps/netutils/)
|
|||
Status: Open. An annoyance, but not a real problem.
|
||||
Priority: Low
|
||||
|
||||
Title: DHCPD ACCESSES KERNEL PRIVATE INTERFACE
|
||||
Description: arp_update() is referenced outside of nuttx/net. It is used in
|
||||
in the netutils/ DHCPD logic to set entries in the ARP table.
|
||||
That is violation of the separation of kernel and OS
|
||||
functionality. As a consequence, dhcpd will not work with the
|
||||
NuttX kernel built.
|
||||
|
||||
This direct OS call needs to be replaced with a network ioctl()
|
||||
call.
|
||||
Status: Open
|
||||
Priority: Medium. Important for full functionality with kernel build.
|
||||
|
||||
Title: NETWORK MONITOR NOT GENERALLY AVAILABLE
|
||||
Description: The NSH network management logic has general applicability
|
||||
but is currently useful only because it is embedded in the NSH
|
||||
|
|
@ -1787,13 +1799,7 @@ o NuttShell (NSH) (apps/nshlib)
|
|||
show status for the single interface on the command line; it will
|
||||
still show status for all interfaces.
|
||||
Status: Open
|
||||
Priority: Low (multiple network interfaces not fully supported yet anyway).
|
||||
|
||||
Title: ARP COMMAND
|
||||
Description: Add an ARP command so that we can see and modify the contents of
|
||||
the ARP table.
|
||||
Status: Open
|
||||
Priority: Low (enhancement)
|
||||
Priority: Low
|
||||
|
||||
Title: ARPPING COMMAND
|
||||
Description: Add an arping command
|
||||
|
|
|
|||
2
arch
2
arch
|
|
@ -1 +1 @@
|
|||
Subproject commit 6190d664666b19580969c4e620646ef4e54f0182
|
||||
Subproject commit feb41dfa8e178a1194fd17afae154bc55912993d
|
||||
10
audio/.gitignore
vendored
Normal file
10
audio/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/Make.dep
|
||||
/.depend
|
||||
/*.asm
|
||||
/*.obj
|
||||
/*.rel
|
||||
/*.lst
|
||||
/*.sym
|
||||
/*.adb
|
||||
/*.lib
|
||||
/*.src
|
||||
|
|
@ -379,7 +379,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
|
||||
case AUDIOIOC_GETCAPS:
|
||||
{
|
||||
FAR struct audio_caps_s *caps = (FAR struct audio_caps_s*)((uintptr_t)arg);
|
||||
FAR struct audio_caps_s *caps = (FAR struct audio_caps_s *)((uintptr_t)arg);
|
||||
DEBUGASSERT(lower->ops->getcaps != NULL);
|
||||
|
||||
audvdbg("AUDIOIOC_GETCAPS: Device=%d\n", caps->ac_type);
|
||||
|
|
@ -393,7 +393,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
case AUDIOIOC_CONFIGURE:
|
||||
{
|
||||
FAR const struct audio_caps_desc_s *caps =
|
||||
(FAR const struct audio_caps_desc_s*)((uintptr_t)arg);
|
||||
(FAR const struct audio_caps_desc_s *)((uintptr_t)arg);
|
||||
DEBUGASSERT(lower->ops->configure != NULL);
|
||||
|
||||
audvdbg("AUDIOIOC_INITIALIZE: Device=%d\n", caps->caps.ac_type);
|
||||
|
|
@ -873,11 +873,11 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev)
|
|||
char path[AUDIO_MAX_DEVICE_PATH];
|
||||
static bool dev_audio_created = false;
|
||||
#ifndef CONFIG_AUDIO_CUSTOM_DEV_PATH
|
||||
const char* devname = "/dev/audio";
|
||||
FAR const char *devname = "/dev/audio";
|
||||
#elif !defined(CONFIG_AUDIO_DEV_ROOT)
|
||||
const char* devname = CONFIG_AUDIO_DEV_PATH;
|
||||
const char* ptr;
|
||||
char* pathptr;
|
||||
FAR const char *devname = CONFIG_AUDIO_DEV_PATH;
|
||||
FAR const char *ptr;
|
||||
FAR char *pathptr;
|
||||
#endif
|
||||
|
||||
/* Allocate the upper-half data structure */
|
||||
|
|
|
|||
|
|
@ -259,23 +259,23 @@ static void pcm_callback(FAR void *arg, uint16_t reason,
|
|||
#ifdef CONFIG_PCM_DEBUG
|
||||
static void pcm_dump(FAR const struct wav_header_s *wav)
|
||||
{
|
||||
dbg( "Wave file header\n");
|
||||
dbg( " Header Chunk:\n");
|
||||
dbg( " Chunk ID: 0x%08x\n", wav->hdr.chunkid);
|
||||
dbg( " Chunk Size: %u\n", wav->hdr.chunklen);
|
||||
dbg( " Format: 0x%08x\n", wav->hdr.format);
|
||||
dbg( " Format Chunk:\n");
|
||||
dbg( " Chunk ID: 0x%08x\n", wav->fmt.chunkid);
|
||||
dbg( " Chunk Size: %u\n", wav->fmt.chunklen);
|
||||
dbg( " Audio Format: 0x%04x\n", wav->fmt.format);
|
||||
dbg( " Num. Channels: %d\n", wav->fmt.nchannels);
|
||||
dbg( " Sample Rate: %u\n", wav->fmt.samprate);
|
||||
dbg( " Byte Rate: %u\n", wav->fmt.byterate);
|
||||
dbg( " Block Align: %d\n", wav->fmt.align);
|
||||
dbg( " Bits Per Sample: %d\n", wav->fmt.bpsamp);
|
||||
dbg( " Data Chunk:\n");
|
||||
dbg( " Chunk ID: 0x%08x\n", wav->data.chunkid);
|
||||
dbg( " Chunk Size: %u\n", wav->data.chunklen);
|
||||
dbg("Wave file header\n");
|
||||
dbg(" Header Chunk:\n");
|
||||
dbg(" Chunk ID: 0x%08x\n", wav->hdr.chunkid);
|
||||
dbg(" Chunk Size: %u\n", wav->hdr.chunklen);
|
||||
dbg(" Format: 0x%08x\n", wav->hdr.format);
|
||||
dbg(" Format Chunk:\n");
|
||||
dbg(" Chunk ID: 0x%08x\n", wav->fmt.chunkid);
|
||||
dbg(" Chunk Size: %u\n", wav->fmt.chunklen);
|
||||
dbg(" Audio Format: 0x%04x\n", wav->fmt.format);
|
||||
dbg(" Num. Channels: %d\n", wav->fmt.nchannels);
|
||||
dbg(" Sample Rate: %u\n", wav->fmt.samprate);
|
||||
dbg(" Byte Rate: %u\n", wav->fmt.byterate);
|
||||
dbg(" Block Align: %d\n", wav->fmt.align);
|
||||
dbg(" Bits Per Sample: %d\n", wav->fmt.bpsamp);
|
||||
dbg(" Data Chunk:\n");
|
||||
dbg(" Chunk ID: 0x%08x\n", wav->data.chunkid);
|
||||
dbg(" Chunk Size: %u\n", wav->data.chunklen);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# nxflat/Makefile
|
||||
#
|
||||
# Copyright (C) 2007-2009, 2012-2014 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2007-2009, 2012-2015 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -46,7 +46,7 @@ CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(TOPDIR)$(DELIM)sched"}
|
|||
BINFMT_ASRCS =
|
||||
BINFMT_CSRCS = binfmt_globals.c binfmt_register.c binfmt_unregister.c
|
||||
BINFMT_CSRCS += binfmt_loadmodule.c binfmt_unloadmodule.c binfmt_execmodule.c
|
||||
BINFMT_CSRCS += binfmt_exec.c binfmt_dumpmodule.c
|
||||
BINFMT_CSRCS += binfmt_exec.c binfmt_copyargv.c binfmt_dumpmodule.c
|
||||
|
||||
ifeq ($(CONFIG_BINFMT_EXEPATH),y)
|
||||
BINFMT_CSRCS += binfmt_exepath.c
|
||||
|
|
@ -56,11 +56,6 @@ ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
|
|||
BINFMT_CSRCS += binfmt_schedunload.c
|
||||
endif
|
||||
|
||||
# Symbol table source files
|
||||
|
||||
BINFMT_CSRCS += symtab_findbyname.c symtab_findbyvalue.c
|
||||
BINFMT_CSRCS += symtab_findorderedbyname.c symtab_findorderedbyvalue.c
|
||||
|
||||
ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
|
||||
BINFMT_CSRCS += binfmt_execsymtab.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* binfmt/binfmt_internal.h
|
||||
* binfmt/binfmt.h
|
||||
*
|
||||
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BINFMT_BINFMT_INTERNAL_H
|
||||
#define __BINFMT_BINFMT_INTERNAL_H
|
||||
#ifndef __BINFMT_BINFMT_H
|
||||
#define __BINFMT_BINFMT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
|
@ -68,9 +68,9 @@ extern "C"
|
|||
|
||||
EXTERN FAR struct binfmt_s *g_binfmts;
|
||||
|
||||
/***********************************************************************
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
***********************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dump_module
|
||||
|
|
@ -92,6 +92,26 @@ int dump_module(FAR const struct binary_s *bin);
|
|||
# define dump_module(bin)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_copyargv
|
||||
*
|
||||
* Description:
|
||||
* In the kernel build, the argv list will likely lie in the caller's
|
||||
* address environment and, hence, by inaccessible when we swith to the
|
||||
* address environment of the new process address environment. So we
|
||||
* do not have any real option other than to copy the callers argv[] list.
|
||||
*
|
||||
* Input Parameter:
|
||||
* bin - Load structure
|
||||
* argv - Argument list
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on sucess; a negater erro value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *argv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_freeargv
|
||||
*
|
||||
|
|
@ -117,5 +137,5 @@ void binfmt_freeargv(FAR struct binary_s *bin);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BINFMT_BINFMT_INTERNAL_H */
|
||||
#endif /* __BINFMT_BINFMT_H */
|
||||
|
||||
197
binfmt/binfmt_copyargv.c
Normal file
197
binfmt/binfmt_copyargv.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/****************************************************************************
|
||||
* binfmt/binfmt_copyargv.c
|
||||
*
|
||||
* Copyright (C) 2009, 2013-2015 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* This is an artificial limit to detect error conditions where an argv[]
|
||||
* list is not properly terminated.
|
||||
*/
|
||||
|
||||
#define MAX_EXEC_ARGS 256
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_copyargv
|
||||
*
|
||||
* Description:
|
||||
* In the kernel build, the argv list will likely lie in the caller's
|
||||
* address environment and, hence, by inaccessible when we switch to the
|
||||
* address environment of the new process address environment. So we
|
||||
* do not have any real option other than to copy the callers argv[] list.
|
||||
*
|
||||
* Input Parameter:
|
||||
* bin - Load structure
|
||||
* argv - Argument list
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on sucess; a negater erro value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *argv)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||
FAR char *ptr;
|
||||
size_t argvsize;
|
||||
size_t argsize;
|
||||
int nargs;
|
||||
int i;
|
||||
|
||||
/* Get the number of arguments and the size of the argument list */
|
||||
|
||||
bin->argv = (FAR char **)NULL;
|
||||
bin->argbuffer = (FAR char *)NULL;
|
||||
|
||||
if (argv)
|
||||
{
|
||||
argsize = 0;
|
||||
nargs = 0;
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
{
|
||||
/* Increment the size of the allocation with the size of the next string */
|
||||
|
||||
argsize += (strlen(argv[i]) + 1);
|
||||
nargs++;
|
||||
|
||||
/* This is a sanity check to prevent running away with an unterminated
|
||||
* argv[] list. MAX_EXEC_ARGS should be sufficiently large that this
|
||||
* never happens in normal usage.
|
||||
*/
|
||||
|
||||
if (nargs > MAX_EXEC_ARGS)
|
||||
{
|
||||
bdbg("ERROR: Too many arguments: %lu\n", (unsigned long)argvsize);
|
||||
return -E2BIG;
|
||||
}
|
||||
}
|
||||
|
||||
bvdbg("args=%d argsize=%lu\n", nargs, (unsigned long)argsize);
|
||||
|
||||
/* Allocate the argv array and an argument buffer */
|
||||
|
||||
if (argsize > 0)
|
||||
{
|
||||
argvsize = (nargs + 1) * sizeof(FAR char *);
|
||||
bin->argbuffer = (FAR char *)kmm_malloc(argvsize + argsize);
|
||||
if (!bin->argbuffer)
|
||||
{
|
||||
bdbg("ERROR: Failed to allocate the argument buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy the argv list */
|
||||
|
||||
bin->argv = (FAR char **)bin->argbuffer;
|
||||
ptr = bin->argbuffer + argvsize;
|
||||
for (i = 0; argv[i]; i++)
|
||||
{
|
||||
bin->argv[i] = ptr;
|
||||
argsize = strlen(argv[i]) + 1;
|
||||
memcpy(ptr, argv[i], argsize);
|
||||
ptr += argsize;
|
||||
}
|
||||
|
||||
/* Terminate the argv[] list */
|
||||
|
||||
bin->argv[i] = (FAR char *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
#else
|
||||
/* Just save the caller's argv pointer */
|
||||
|
||||
bin->argv = argv;
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_freeargv
|
||||
*
|
||||
* Description:
|
||||
* Release the copied argv[] list.
|
||||
*
|
||||
* Input Parameter:
|
||||
* binp - Load structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||
void binfmt_freeargv(FAR struct binary_s *binp)
|
||||
{
|
||||
/* Is there an allocated argument buffer */
|
||||
|
||||
if (binp->argbuffer)
|
||||
{
|
||||
/* Free the argument buffer */
|
||||
|
||||
kmm_free(binp->argbuffer);
|
||||
}
|
||||
|
||||
/* Nullify the allocated argv[] array and the argument buffer pointers */
|
||||
|
||||
binp->argbuffer = (FAR char *)NULL;
|
||||
binp->argv = (FAR char **)NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CONFIG_BINFMT_DISABLE */
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT) && !defined(CONFIG_BINFMT_DISABLE)
|
||||
|
||||
|
|
@ -65,11 +65,11 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
/****************************************************************************
|
||||
* Name: dump_module
|
||||
*
|
||||
* Description:
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
* 0 (OK) is returned on success and a negated errno is returned on
|
||||
* failure.
|
||||
*
|
||||
***********************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
int dump_module(FAR const struct binary_s *bin)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,129 +46,10 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* This is an artificial limit to detect error conditions where an argv[]
|
||||
* list is not properly terminated.
|
||||
*/
|
||||
|
||||
#define MAX_EXEC_ARGS 256
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_copyargv
|
||||
*
|
||||
* Description:
|
||||
* In the kernel build, the argv list will likely lie in the caller's
|
||||
* address environment and, hence, by inaccessible when we swith to the
|
||||
* address environment of the new process address environment. So we
|
||||
* do not have any real option other than to copy the callers argv[] list.
|
||||
*
|
||||
* Input Parameter:
|
||||
* bin - Load structure
|
||||
* argv - Argument list
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on sucess; a negater erro value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int binfmt_copyargv(FAR struct binary_s *bin, FAR char * const *argv)
|
||||
{
|
||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||
FAR char *ptr;
|
||||
size_t argvsize;
|
||||
size_t argsize;
|
||||
int nargs;
|
||||
int i;
|
||||
|
||||
/* Get the number of arguments and the size of the argument list */
|
||||
|
||||
bin->argv = (FAR char **)NULL;
|
||||
bin->argbuffer = (FAR char *)NULL;
|
||||
|
||||
if (argv)
|
||||
{
|
||||
argsize = 0;
|
||||
nargs = 0;
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
{
|
||||
/* Increment the size of the allocation with the size of the next string */
|
||||
|
||||
argsize += (strlen(argv[i]) + 1);
|
||||
nargs++;
|
||||
|
||||
/* This is a sanity check to prevent running away with an unterminated
|
||||
* argv[] list. MAX_EXEC_ARGS should be sufficiently large that this
|
||||
* never happens in normal usage.
|
||||
*/
|
||||
|
||||
if (nargs > MAX_EXEC_ARGS)
|
||||
{
|
||||
bdbg("ERROR: Too many arguments: %lu\n", (unsigned long)argvsize);
|
||||
return -E2BIG;
|
||||
}
|
||||
}
|
||||
|
||||
bvdbg("args=%d argsize=%lu\n", nargs, (unsigned long)argsize);
|
||||
|
||||
/* Allocate the argv array and an argument buffer */
|
||||
|
||||
if (argsize > 0)
|
||||
{
|
||||
argvsize = (nargs + 1) * sizeof(FAR char *);
|
||||
bin->argbuffer = (FAR char *)kmm_malloc(argvsize + argsize);
|
||||
if (!bin->argbuffer)
|
||||
{
|
||||
bdbg("ERROR: Failed to allocate the argument buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy the argv list */
|
||||
|
||||
bin->argv = (FAR char **)bin->argbuffer;
|
||||
ptr = bin->argbuffer + argvsize;
|
||||
for (i = 0; argv[i]; i++)
|
||||
{
|
||||
bin->argv[i] = ptr;
|
||||
argsize = strlen(argv[i]) + 1;
|
||||
memcpy(ptr, argv[i], argsize);
|
||||
ptr += argsize;
|
||||
}
|
||||
|
||||
/* Terminate the argv[] list */
|
||||
|
||||
bin->argv[i] = (FAR char *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
#else
|
||||
/* Just save the caller's argv pointer */
|
||||
|
||||
bin->argv = argv;
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||
|
||||
/* Allocate a TCB for the new task. */
|
||||
|
||||
tcb = (FAR struct task_tcb_s*)kmm_zalloc(sizeof(struct task_tcb_s));
|
||||
tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s));
|
||||
if (!tcb)
|
||||
{
|
||||
err = ENOMEM;
|
||||
|
|
@ -189,7 +189,7 @@ int exec_module(FAR const struct binary_s *binp)
|
|||
* will need to change if/when we want to support dynamic stack allocation.
|
||||
*/
|
||||
|
||||
stack = (FAR uint32_t*)kumm_malloc(binp->stacksize);
|
||||
stack = (FAR uint32_t *)kumm_malloc(binp->stacksize);
|
||||
if (!stack)
|
||||
{
|
||||
err = ENOMEM;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* binfmt/binfmt_execsymtab.c
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/binfmt/symtab.h>
|
||||
|
||||
|
|
@ -68,7 +69,7 @@
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_EXECFUNCS_HAVE_SYMTAB
|
||||
|
|
@ -116,10 +117,10 @@ void exec_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols)
|
|||
* size are returned as a single atomic operation.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
*symtab = g_exec_symtab;
|
||||
*nsymbols = g_exec_nsymbols;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -147,10 +148,10 @@ void exec_setsymtab(FAR const struct symtab_s *symtab, int nsymbols)
|
|||
* size are set as a single atomic operation.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
g_exec_symtab = symtab;
|
||||
g_exec_nsymbols = nsymbols;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LIBC_EXECFUNCS */
|
||||
|
|
@ -142,7 +142,7 @@ EXEPATH_HANDLE exepath_init(void)
|
|||
return (EXEPATH_HANDLE)exepath;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: exepath_next
|
||||
*
|
||||
* Description:
|
||||
|
|
@ -190,7 +190,7 @@ FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath)
|
|||
* in the PATH variable have been considered.
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
/* Make sure that exepath->next points to the beginning of a string */
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath)
|
|||
|
||||
/* Verify that a regular file exists at this path */
|
||||
|
||||
ret = stat(fullpath, &buf);;
|
||||
ret = stat(fullpath, &buf);
|
||||
if (ret == OK && S_ISREG(buf.st_mode))
|
||||
{
|
||||
return fullpath;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* binfmt/binfmt_schedunload.c
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -43,10 +43,11 @@
|
|||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#if !defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_SCHED_HAVE_PARENT)
|
||||
|
||||
|
|
@ -84,7 +85,7 @@ FAR struct binary_s *g_unloadhead;
|
|||
* pid - The task ID of the child task
|
||||
* bin - This structure must have been allocated with kmm_malloc() and must
|
||||
* persist until the task unloads
|
||||
|
||||
*
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
|
|
@ -105,10 +106,10 @@ static void unload_list_add(pid_t pid, FAR struct binary_s *bin)
|
|||
* interrupts.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
bin->flink = g_unloadhead;
|
||||
g_unloadhead = bin;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -313,13 +314,13 @@ int schedule_unload(pid_t pid, FAR struct binary_s *bin)
|
|||
|
||||
/* Emergency removal from the list */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
if (unload_list_remove(pid) != bin)
|
||||
{
|
||||
blldbg("ERROR: Failed to remove structure\n");
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
|
|
@ -211,38 +211,5 @@ int unload_module(FAR struct binary_s *binp)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binfmt_freeargv
|
||||
*
|
||||
* Description:
|
||||
* Release the copied argv[] list.
|
||||
*
|
||||
* Input Parameter:
|
||||
* binp - Load structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
|
||||
void binfmt_freeargv(FAR struct binary_s *binp)
|
||||
{
|
||||
/* Is there an allocated argument buffer */
|
||||
|
||||
if (binp->argbuffer)
|
||||
{
|
||||
/* Free the argument buffer */
|
||||
|
||||
kmm_free(binp->argbuffer);
|
||||
}
|
||||
|
||||
/* Nullify the allocated argv[] array and the argument buffer pointers */
|
||||
|
||||
binp->argbuffer = (FAR char *)NULL;
|
||||
binp->argv = (FAR char **)NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_BINFMT_DISABLE */
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
#include <nuttx/binfmt/binfmt.h>
|
||||
|
||||
#include "binfmt_internal.h"
|
||||
#include "binfmt.h"
|
||||
|
||||
#ifndef CONFIG_BINFMT_DISABLE
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ static int builtin_loadbinary(struct binary_s *binp)
|
|||
{
|
||||
int errval = get_errno();
|
||||
bdbg("ERROR: FIOC_FILENAME ioctl failed: %d\n", errval);
|
||||
close(fd);
|
||||
return -errval;
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +129,7 @@ static int builtin_loadbinary(struct binary_s *binp)
|
|||
{
|
||||
int errval = get_errno();
|
||||
bdbg("ERROR: %s is not a builtin application\n", filename);
|
||||
close(fd);
|
||||
return -errval;
|
||||
|
||||
}
|
||||
|
|
@ -140,6 +142,7 @@ static int builtin_loadbinary(struct binary_s *binp)
|
|||
binp->entrypt = b->main;
|
||||
binp->stacksize = b->stacksize;
|
||||
binp->priority = b->priority;
|
||||
close(fd);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ static void elf_dumpentrypt(FAR struct binary_s *binp,
|
|||
}
|
||||
#endif
|
||||
|
||||
elf_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
|
||||
elf_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt,
|
||||
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
|
|
|
|||
|
|
@ -49,11 +49,7 @@
|
|||
#include <nuttx/binfmt/elf.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static inline int elf_readrel(FAR struct elf_loadinfo_s *loadinfo,
|
|||
|
||||
/* And, finally, read the symbol table entry into memory */
|
||||
|
||||
return elf_read(loadinfo, (FAR uint8_t*)rel, sizeof(Elf32_Rel), offset);
|
||||
return elf_read(loadinfo, (FAR uint8_t *)rel, sizeof(Elf32_Rel), offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
{
|
||||
/* Allocate memory to hold a copy of the .ctor section */
|
||||
|
||||
loadinfo->ctoralloc = (binfmt_ctor_t*)kumm_malloc(ctorsize);
|
||||
loadinfo->ctoralloc = (binfmt_ctor_t *)kumm_malloc(ctorsize);
|
||||
if (!loadinfo->ctoralloc)
|
||||
{
|
||||
bdbg("Failed to allocate memory for .ctors\n");
|
||||
|
|
@ -174,7 +174,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
|
||||
/* Read the section header table into memory */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize,
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->ctors, ctorsize,
|
||||
shdr->sh_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
@ -206,7 +206,7 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
* will be relocated via the normal mechanism.
|
||||
*/
|
||||
|
||||
loadinfo->ctors = (binfmt_ctor_t*)shdr->sh_addr;
|
||||
loadinfo->ctors = (binfmt_ctor_t *)shdr->sh_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
{
|
||||
/* Allocate memory to hold a copy of the .dtor section */
|
||||
|
||||
loadinfo->ctoralloc = (binfmt_dtor_t*)kumm_malloc(dtorsize);
|
||||
loadinfo->ctoralloc = (binfmt_dtor_t *)kumm_malloc(dtorsize);
|
||||
if (!loadinfo->ctoralloc)
|
||||
{
|
||||
bdbg("Failed to allocate memory for .dtors\n");
|
||||
|
|
@ -174,7 +174,7 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
|
||||
/* Read the section header table into memory */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->dtors, dtorsize,
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->dtors, dtorsize,
|
||||
shdr->sh_offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
@ -206,7 +206,7 @@ int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo)
|
|||
* will be relocated via the normal mechanism.
|
||||
*/
|
||||
|
||||
loadinfo->dtors = (binfmt_dtor_t*)shdr->sh_addr;
|
||||
loadinfo->dtors = (binfmt_dtor_t *)shdr->sh_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -172,19 +172,19 @@ int elf_init(FAR const char *filename, FAR struct elf_loadinfo_s *loadinfo)
|
|||
|
||||
/* Read the ELF ehdr from offset 0 */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t*)&loadinfo->ehdr, sizeof(Elf32_Ehdr), 0);
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)&loadinfo->ehdr, sizeof(Elf32_Ehdr), 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("Failed to read ELF header: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
elf_dumpbuffer("ELF header", (FAR const uint8_t*)&loadinfo->ehdr, sizeof(Elf32_Ehdr));
|
||||
elf_dumpbuffer("ELF header", (FAR const uint8_t *)&loadinfo->ehdr, sizeof(Elf32_Ehdr));
|
||||
|
||||
/* Verify the ELF header */
|
||||
|
||||
ret = elf_verifyheader(&loadinfo->ehdr);
|
||||
if (ret <0)
|
||||
if (ret < 0)
|
||||
{
|
||||
/* This may not be an error because we will be called to attempt loading
|
||||
* EVERY binary. If elf_verifyheader() does not recognize the ELF header,
|
||||
|
|
|
|||
|
|
@ -157,8 +157,8 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
|
|||
/* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
|
||||
|
||||
bvdbg("Loaded sections:\n");
|
||||
text = (FAR uint8_t*)loadinfo->textalloc;
|
||||
data = (FAR uint8_t*)loadinfo->dataalloc;
|
||||
text = (FAR uint8_t *)loadinfo->textalloc;
|
||||
data = (FAR uint8_t *)loadinfo->dataalloc;
|
||||
|
||||
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@
|
|||
****************************************************************************/
|
||||
|
||||
#if defined(ELF_DUMP_READDATA)
|
||||
static inline void elf_dumpreaddata(char *buffer, int buflen)
|
||||
static inline void elf_dumpreaddata(FAR char *buffer, int buflen)
|
||||
{
|
||||
uint32_t *buf32 = (uint32_t*)buffer;
|
||||
FAR uint32_t *buf32 = (FAR uint32_t *)buffer;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
|
|||
buffer = loadinfo->iobuffer;
|
||||
bytesread = 0;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
/* Get the number of bytes to read */
|
||||
|
||||
|
|
@ -211,16 +211,18 @@ int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
|
|||
|
||||
/* Allocate memory to hold a working copy of the sector header table */
|
||||
|
||||
loadinfo->shdr = (FAR Elf32_Shdr*)kmm_malloc(shdrsize);
|
||||
loadinfo->shdr = (FAR FAR Elf32_Shdr *)kmm_malloc(shdrsize);
|
||||
if (!loadinfo->shdr)
|
||||
{
|
||||
bdbg("Failed to allocate the section header table. Size: %ld\n", (long)shdrsize);
|
||||
bdbg("Failed to allocate the section header table. Size: %ld\n",
|
||||
(long)shdrsize);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Read the section header table into memory */
|
||||
|
||||
ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->shdr, shdrsize, loadinfo->ehdr.e_shoff);
|
||||
ret = elf_read(loadinfo, (FAR uint8_t *)loadinfo->shdr, shdrsize,
|
||||
loadinfo->ehdr.e_shoff);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("Failed to read section header table: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ static int elf_symname(FAR struct elf_loadinfo_s *loadinfo,
|
|||
|
||||
bytesread = 0;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
/* Get the number of bytes to read */
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index,
|
|||
|
||||
/* And, finally, read the symbol table entry into memory */
|
||||
|
||||
return elf_read(loadinfo, (FAR uint8_t*)sym, sizeof(Elf32_Sym), offset);
|
||||
return elf_read(loadinfo, (FAR uint8_t *)sym, sizeof(Elf32_Sym), offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@
|
|||
* Private Constant Data
|
||||
****************************************************************************/
|
||||
|
||||
static const char g_elfmagic[EI_MAGIC_SIZE] = { 0x7f, 'E', 'L', 'F' };
|
||||
static const char g_elfmagic[EI_MAGIC_SIZE] =
|
||||
{
|
||||
0x7f, 'E', 'L', 'F'
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
|
|
|||
|
|
@ -102,14 +102,14 @@
|
|||
static inline int nxflat_bindrel32i(FAR struct nxflat_loadinfo_s *loadinfo,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t *addr;
|
||||
FAR uint32_t *addr;
|
||||
|
||||
bvdbg("NXFLAT_RELOC_TYPE_REL32I Offset: %08x I-Space: %p\n",
|
||||
offset, loadinfo->ispace + sizeof(struct nxflat_hdr_s));
|
||||
|
||||
if (offset < loadinfo->dsize)
|
||||
{
|
||||
addr = (uint32_t*)(offset + loadinfo->dspace->region);
|
||||
addr = (FAR uint32_t *)(offset + loadinfo->dspace->region);
|
||||
bvdbg(" Before: %08x\n", *addr);
|
||||
*addr += (uint32_t)(loadinfo->ispace + sizeof(struct nxflat_hdr_s));
|
||||
bvdbg(" After: %08x\n", *addr);
|
||||
|
|
@ -141,14 +141,14 @@ static inline int nxflat_bindrel32i(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
static inline int nxflat_bindrel32d(FAR struct nxflat_loadinfo_s *loadinfo,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t *addr;
|
||||
FAR uint32_t *addr;
|
||||
|
||||
bvdbg("NXFLAT_RELOC_TYPE_REL32D Offset: %08x D-Space: %p\n",
|
||||
offset, loadinfo->dspace->region);
|
||||
|
||||
if (offset < loadinfo->dsize)
|
||||
{
|
||||
addr = (uint32_t*)(offset + loadinfo->dspace->region);
|
||||
addr = (FAR uint32_t *)(offset + loadinfo->dspace->region);
|
||||
bvdbg(" Before: %08x\n", *addr);
|
||||
*addr += (uint32_t)(loadinfo->dspace->region);
|
||||
bvdbg(" After: %08x\n", *addr);
|
||||
|
|
@ -183,14 +183,14 @@ static inline int nxflat_bindrel32d(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
static inline int nxflat_bindrel32id(FAR struct nxflat_loadinfo_s *loadinfo,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t *addr;
|
||||
FAR uint32_t *addr;
|
||||
|
||||
bvdbg("NXFLAT_RELOC_TYPE_REL32D Offset: %08x D-Space: %p\n",
|
||||
offset, loadinfo->dspace->region);
|
||||
|
||||
if (offset < loadinfo->dsize)
|
||||
{
|
||||
addr = (uint32_t*)(offset + loadinfo->dspace->region);
|
||||
addr = (FAR uint32_t *)(offset + loadinfo->dspace->region);
|
||||
bvdbg(" Before: %08x\n", *addr);
|
||||
*addr += ((uint32_t)loadinfo->ispace - (uint32_t)(loadinfo->dspace->region));
|
||||
bvdbg(" After: %08x\n", *addr);
|
||||
|
|
@ -231,7 +231,7 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
|
|||
|
||||
/* The NXFLAT header is the first thing at the beginning of the ISpace. */
|
||||
|
||||
hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace;
|
||||
hdr = (FAR struct nxflat_hdr_s *)loadinfo->ispace;
|
||||
|
||||
/* From this, we can get the offset to the list of relocation entries */
|
||||
|
||||
|
|
@ -348,8 +348,8 @@ static inline int nxflat_gotrelocs(FAR struct nxflat_loadinfo_s *loadinfo)
|
|||
#ifdef CONFIG_NXFLAT_DUMPBUFFER
|
||||
if (ret == OK && nrelocs > 0)
|
||||
{
|
||||
relocs = (FAR struct nxflat_reloc_s*)(offset - loadinfo->isize + loadinfo->dspace->region);
|
||||
nxflat_dumpbuffer("GOT", (FAR const uint8_t*)relocs, nrelocs * sizeof(struct nxflat_reloc_s));
|
||||
relocs = (FAR struct nxflat_reloc_s *)(offset - loadinfo->isize + loadinfo->dspace->region);
|
||||
nxflat_dumpbuffer("GOT", (FAR const uint8_t *)relocs, nrelocs * sizeof(struct nxflat_reloc_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
|
||||
/* The NXFLAT header is the first thing at the beginning of the ISpace. */
|
||||
|
||||
hdr = (FAR struct nxflat_hdr_s*)loadinfo->ispace;
|
||||
hdr = (FAR struct nxflat_hdr_s *)loadinfo->ispace;
|
||||
|
||||
/* From this, we can get the offset to the list of symbols imported by
|
||||
* this module and the number of symbols imported by this module.
|
||||
|
|
@ -440,7 +440,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
DEBUGASSERT(offset >= loadinfo->isize &&
|
||||
offset < loadinfo->isize + loadinfo->dsize);
|
||||
|
||||
imports = (struct nxflat_import_s*)
|
||||
imports = (FAR struct nxflat_import_s *)
|
||||
(offset - loadinfo->isize + loadinfo->dspace->region);
|
||||
|
||||
/* Now, traverse the list of imported symbols and attempt to bind
|
||||
|
|
@ -462,7 +462,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
offset = imports[i].i_funcname;
|
||||
DEBUGASSERT(offset < loadinfo->isize);
|
||||
|
||||
symname = (char*)(offset + loadinfo->ispace + sizeof(struct nxflat_hdr_s));
|
||||
symname = (FAR char *)(offset + loadinfo->ispace + sizeof(struct nxflat_hdr_s));
|
||||
|
||||
/* Find the exported symbol value for this this symbol name. */
|
||||
|
||||
|
|
@ -494,7 +494,7 @@ static inline int nxflat_bindimports(FAR struct nxflat_loadinfo_s *loadinfo,
|
|||
#ifdef CONFIG_NXFLAT_DUMPBUFFER
|
||||
if (nimports > 0)
|
||||
{
|
||||
nxflat_dumpbuffer("Imports", (FAR const uint8_t*)imports, nimports * sizeof(struct nxflat_import_s));
|
||||
nxflat_dumpbuffer("Imports", (FAR const uint8_t *)imports, nimports * sizeof(struct nxflat_import_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -549,7 +549,7 @@ static inline int nxflat_clearbss(FAR struct nxflat_loadinfo_s *loadinfo)
|
|||
|
||||
/* Zero the BSS area */
|
||||
|
||||
memset((void*)(loadinfo->dspace->region + loadinfo->datasize), 0,
|
||||
memset((FAR void *)(loadinfo->dspace->region + loadinfo->datasize), 0,
|
||||
loadinfo->bsssize);
|
||||
|
||||
/* Restore the original address environment */
|
||||
|
|
|
|||
|
|
@ -118,14 +118,15 @@ int nxflat_init(const char *filename, struct nxflat_loadinfo_s *loadinfo)
|
|||
|
||||
/* Read the NXFLAT header from offset 0 */
|
||||
|
||||
ret = nxflat_read(loadinfo, (char*)&loadinfo->header,
|
||||
ret = nxflat_read(loadinfo, (FAR char *)&loadinfo->header,
|
||||
sizeof(struct nxflat_hdr_s), 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("Failed to read NXFLAT header: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
nxflat_dumpbuffer("NXFLAT header", (FAR const uint8_t*)&loadinfo->header,
|
||||
|
||||
nxflat_dumpbuffer("NXFLAT header", (FAR const uint8_t *)&loadinfo->header,
|
||||
sizeof(struct nxflat_hdr_s));
|
||||
|
||||
/* Verify the NXFLAT header */
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo)
|
|||
*/
|
||||
|
||||
loadinfo->ispace = (uint32_t)mmap(NULL, loadinfo->isize, PROT_READ,
|
||||
MAP_SHARED|MAP_FILE, loadinfo->filfd, 0);
|
||||
MAP_SHARED | MAP_FILE, loadinfo->filfd, 0);
|
||||
if (loadinfo->ispace == (uint32_t)MAP_FAILED)
|
||||
{
|
||||
bdbg("Failed to map NXFLAT ISpace: %d\n", errno);
|
||||
|
|
@ -189,7 +189,8 @@ int nxflat_load(struct nxflat_loadinfo_s *loadinfo)
|
|||
* DSpace memory.
|
||||
*/
|
||||
|
||||
ret = nxflat_read(loadinfo, (char*)loadinfo->dspace->region, dreadsize, doffset);
|
||||
ret = nxflat_read(loadinfo, (FAR char *)loadinfo->dspace->region,
|
||||
dreadsize, doffset);
|
||||
if (ret < 0)
|
||||
{
|
||||
bdbg("Failed to read .data section: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@
|
|||
****************************************************************************/
|
||||
|
||||
#if defined(NXFLAT_DUMP_READDATA)
|
||||
static inline void nxflat_dumpreaddata(char *buffer, int buflen)
|
||||
static inline void nxflat_dumpreaddata(FAR char *buffer, int buflen)
|
||||
{
|
||||
uint32_t *buf32 = (uint32_t*)buffer;
|
||||
FAR uint32_t *buf32 = (FAR uint32_t *)buffer;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,14 +79,14 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxflat_unload(struct nxflat_loadinfo_s *loadinfo)
|
||||
int nxflat_unload(FAR struct nxflat_loadinfo_s *loadinfo)
|
||||
{
|
||||
/* Release the memory segments */
|
||||
/* Release the I-Space mmap'ed file */
|
||||
|
||||
if (loadinfo->ispace)
|
||||
{
|
||||
munmap((void*)loadinfo->ispace, loadinfo->isize);
|
||||
munmap((FAR void *)loadinfo->ispace, loadinfo->isize);
|
||||
loadinfo->ispace = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ Files include in this directory include:
|
|||
xxd -g 1 -i romfs.img >romfs.h
|
||||
|
||||
then cleaned up with an editor to conform with NuttX coding standards.
|
||||
Also, the data definitions in the romfs.h file should be marked with
|
||||
'const' qualifier the so that the data will be stored in FLASH.
|
||||
|
||||
Test Configuration
|
||||
------------------
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ static int nxflat_loadbinary(struct binary_s *binp)
|
|||
*/
|
||||
|
||||
binp->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
|
||||
binp->mapped = (void*)loadinfo.ispace;
|
||||
binp->mapped = (FAR void *)loadinfo.ispace;
|
||||
binp->mapsize = loadinfo.isize;
|
||||
binp->stacksize = loadinfo.stacksize;
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ static int nxflat_loadbinary(struct binary_s *binp)
|
|||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
# warning "REVISIT"
|
||||
#else
|
||||
binp->alloc[0] = (void*)loadinfo.dspace;
|
||||
binp->alloc[0] = (FAR void *)loadinfo.dspace;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
|
|
@ -213,7 +213,7 @@ static int nxflat_loadbinary(struct binary_s *binp)
|
|||
up_addrenv_clone(&loadinfo.addrenv, &binp->addrenv);
|
||||
#endif
|
||||
|
||||
nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
|
||||
nxflat_dumpbuffer("Entry code", (FAR const uint8_t *)binp->entrypt,
|
||||
MIN(loadinfo.isize - loadinfo.entryoffs, 512));
|
||||
|
||||
nxflat_uninit(&loadinfo);
|
||||
|
|
@ -227,11 +227,11 @@ errout:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
/****************************************************************************
|
||||
* Name: nxflat_initialize
|
||||
*
|
||||
* Description:
|
||||
|
|
@ -244,7 +244,7 @@ errout:
|
|||
* 0 (OK) is returned on success and a negated errno is returned on
|
||||
* failure.
|
||||
*
|
||||
***********************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
int nxflat_initialize(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ static int pcode_load(struct binary_s *binp)
|
|||
{
|
||||
/* Set up for the next gulp */
|
||||
|
||||
DEBUGASSERT(nread > 0 && nread <=remaining);
|
||||
DEBUGASSERT(nread > 0 && nread <= remaining);
|
||||
remaining -= nread;
|
||||
ptr += nread;
|
||||
}
|
||||
|
|
|
|||
2
configs
2
configs
|
|
@ -1 +1 @@
|
|||
Subproject commit ac4035687c824bb4a573e06feb017cb4f3ce7626
|
||||
Subproject commit f7c42ff4a006f5d37fa6a818aafaf20886309fd1
|
||||
|
|
@ -39,4 +39,15 @@ config CRYPTO_CRYPTODEV
|
|||
bool "cryptodev support"
|
||||
default n
|
||||
|
||||
endif
|
||||
config CRYPTO_SW_AES
|
||||
bool "Software AES library"
|
||||
default n
|
||||
---help---
|
||||
Enable the software AES library as described in
|
||||
include/nuttx/crypto/aes.h
|
||||
|
||||
TODO: Adapt interfaces so that they are consistent with H/W AES
|
||||
implemenations. This needs to support up_aesinitialize() and
|
||||
aes_cypher() per include/nuttx/crypto/crypto.h.
|
||||
|
||||
endif # CRYPTO
|
||||
|
|
|
|||
|
|
@ -35,33 +35,41 @@
|
|||
|
||||
-include $(TOPDIR)/Make.defs
|
||||
|
||||
CRYPTO_ASRCS =
|
||||
CRYPTO_CSRCS =
|
||||
|
||||
ifeq ($(CONFIG_CRYPTO),y)
|
||||
|
||||
# Basic
|
||||
|
||||
CRYPTO_ASRCS =
|
||||
CRYPTO_CSRCS = crypto.c testmngr.c
|
||||
CRYPTO_CSRCS += crypto.c testmngr.c
|
||||
|
||||
# cryptodev support
|
||||
|
||||
ifeq ($(CONFIG_CRYPTO_CRYPTODEV),y)
|
||||
CRYPTO_CSRCS += cryptodev.c
|
||||
CRYPTO_CSRCS += cryptodev.c
|
||||
endif
|
||||
|
||||
# Sofware AES library
|
||||
|
||||
ifeq ($(CONFIG_CRYPTO_SW_AES),y)
|
||||
CRYPTO_CSRCS += aes.c
|
||||
endif
|
||||
|
||||
endif # CONFIG_CRYPTO
|
||||
|
||||
ASRCS = $(CRYPTO_ASRCS)
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
ASRCS = $(CRYPTO_ASRCS)
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
|
||||
CSRCS = $(CRYPTO_CSRCS)
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
CSRCS = $(CRYPTO_CSRCS)
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
|
||||
SRCS = $(ASRCS) $(CSRCS)
|
||||
OBJS = $(AOBJS) $(COBJS)
|
||||
SRCS = $(ASRCS) $(CSRCS)
|
||||
OBJS = $(AOBJS) $(COBJS)
|
||||
|
||||
BIN = libcrypto$(LIBEXT)
|
||||
BIN = libcrypto$(LIBEXT)
|
||||
|
||||
all: $(BIN)
|
||||
all: $(BIN)
|
||||
|
||||
$(AOBJS): %$(OBJEXT): %.S
|
||||
$(call ASSEMBLE, $<, $@)
|
||||
|
|
|
|||
594
crypto/aes.c
Normal file
594
crypto/aes.c
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
/****************************************************************************
|
||||
* crypto/aes.c
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Extracted from the CC3000 Host Driver Implementation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Neither the name of Texas Instruments Incorporated 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* TODO: Adapt interfaces so that they are consistent with H/W AES
|
||||
* implemenations. This needs to support up_aesinitialize() and
|
||||
* aes_cypher() per include/nuttx/crypto/crypto.h.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/crypto/aes.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Forward sbox */
|
||||
|
||||
static const uint8_t g_sbox[256] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, /* 0 */
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, /* 1 */
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, /* 2 */
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, /* 3 */
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, /* 4 */
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, /* 5 */
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, /* 6 */
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, /* 7 */
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, /* 8 */
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, /* 9 */
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, /* A */
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, /* B */
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, /* C */
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, /* D */
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, /* E */
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 /* F */
|
||||
};
|
||||
|
||||
/* Inverse sbox */
|
||||
|
||||
static const uint8_t g_rsbox[256] =
|
||||
{
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
};
|
||||
|
||||
/* Round constant */
|
||||
|
||||
static const uint8_t g_rcon[11] =
|
||||
{
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
|
||||
};
|
||||
|
||||
static uint8_t g_expanded_key[176];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: expand_key
|
||||
*
|
||||
* Description:
|
||||
* Expend a 16 bytes key for AES128 implementation
|
||||
*
|
||||
* Input Parameters:
|
||||
* key AES128 key - 16 bytes
|
||||
* expanded_key expanded AES128 key
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void expand_key(FAR uint8_t *expanded_key, FAR const uint8_t *key)
|
||||
{
|
||||
uint16_t buf1;
|
||||
uint16_t ii;
|
||||
|
||||
for (ii = 0; ii < 16; ii++)
|
||||
{
|
||||
expanded_key[ii] = key[ii];
|
||||
}
|
||||
|
||||
for (ii = 1; ii < 11; ii++)
|
||||
{
|
||||
buf1 = expanded_key[ii*16 - 4];
|
||||
expanded_key[ii * 16 + 0] = g_sbox[expanded_key[ii *16 - 3]] ^ expanded_key[(ii - 1) * 16 + 0] ^ g_rcon[ii];
|
||||
expanded_key[ii * 16 + 1] = g_sbox[expanded_key[ii *16 - 2]] ^ expanded_key[(ii - 1) * 16 + 1];
|
||||
expanded_key[ii * 16 + 2] = g_sbox[expanded_key[ii *16 - 1]] ^ expanded_key[(ii - 1) * 16 + 2];
|
||||
expanded_key[ii * 16 + 3] = g_sbox[buf1] ^ expanded_key[(ii - 1) * 16 + 3];
|
||||
expanded_key[ii * 16 + 4] = expanded_key[(ii - 1) * 16 + 4] ^ expanded_key[ii * 16 + 0];
|
||||
expanded_key[ii * 16 + 5] = expanded_key[(ii - 1) * 16 + 5] ^ expanded_key[ii * 16 + 1];
|
||||
expanded_key[ii * 16 + 6] = expanded_key[(ii - 1) * 16 + 6] ^ expanded_key[ii * 16 + 2];
|
||||
expanded_key[ii * 16 + 7] = expanded_key[(ii - 1) * 16 + 7] ^ expanded_key[ii * 16 + 3];
|
||||
expanded_key[ii * 16 + 8] = expanded_key[(ii - 1) * 16 + 8] ^ expanded_key[ii * 16 + 4];
|
||||
expanded_key[ii * 16 + 9] = expanded_key[(ii - 1) * 16 + 9] ^ expanded_key[ii * 16 + 5];
|
||||
expanded_key[ii * 16 +10] = expanded_key[(ii - 1) * 16 +10] ^ expanded_key[ii * 16 + 6];
|
||||
expanded_key[ii * 16 +11] = expanded_key[(ii - 1) * 16 +11] ^ expanded_key[ii * 16 + 7];
|
||||
expanded_key[ii * 16 +12] = expanded_key[(ii - 1) * 16 +12] ^ expanded_key[ii * 16 + 8];
|
||||
expanded_key[ii * 16 +13] = expanded_key[(ii - 1) * 16 +13] ^ expanded_key[ii * 16 + 9];
|
||||
expanded_key[ii * 16 +14] = expanded_key[(ii - 1) * 16 +14] ^ expanded_key[ii * 16 +10];
|
||||
expanded_key[ii * 16 +15] = expanded_key[(ii - 1) * 16 +15] ^ expanded_key[ii * 16 +11];
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Name: galois_mul2
|
||||
*
|
||||
* Description:
|
||||
* Multiply by 2 in the galois field
|
||||
*
|
||||
* Input Parameters:
|
||||
* value argument to multiply
|
||||
*
|
||||
* Returned Value:
|
||||
* Multiplied argument
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static uint8_t galois_mul2(uint8_t value)
|
||||
{
|
||||
if (value >> 7)
|
||||
{
|
||||
value = value << 1;
|
||||
return (value ^ 0x1b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return value << 1;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Name: aes_encr
|
||||
*
|
||||
* Description:
|
||||
* Internal implementation of AES128 encryption.
|
||||
* Straight forward aes encryption implementation. First the group of
|
||||
* operations:
|
||||
*
|
||||
* - addRoundKey
|
||||
* - subbytes
|
||||
* - shiftrows
|
||||
* - mixcolums
|
||||
*
|
||||
* is executed 9 times, after this addroundkey to finish the 9th round, after
|
||||
* that the 10th round without mixcolums no further subfunctions to save
|
||||
* cycles for function calls no structuring with "for (....)" to save cycles.
|
||||
*
|
||||
* Input Parameters:
|
||||
* expanded_key expanded AES128 key
|
||||
* state 16 bytes of plain text and cipher text
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void aes_encr(FAR uint8_t *state, FAR const uint8_t *expanded_key)
|
||||
{
|
||||
uint8_t buf1;
|
||||
uint8_t buf2;
|
||||
uint8_t buf3;
|
||||
uint8_t round;
|
||||
|
||||
for (round = 0; round < 9; round ++)
|
||||
{
|
||||
/* addroundkey, sbox and shiftrows */
|
||||
/* Row 0 */
|
||||
|
||||
state[0] = g_sbox[(state[0] ^ expanded_key[(round * 16)])];
|
||||
state[4] = g_sbox[(state[4] ^ expanded_key[(round * 16) + 4])];
|
||||
state[8] = g_sbox[(state[8] ^ expanded_key[(round * 16) + 8])];
|
||||
state[12] = g_sbox[(state[12] ^ expanded_key[(round * 16) + 12])];
|
||||
|
||||
/* Row 1 */
|
||||
|
||||
buf1 = state[1] ^ expanded_key[(round * 16) + 1];
|
||||
state[1] = g_sbox[(state[5] ^ expanded_key[(round * 16) + 5])];
|
||||
state[5] = g_sbox[(state[9] ^ expanded_key[(round * 16) + 9])];
|
||||
state[9] = g_sbox[(state[13] ^ expanded_key[(round * 16) + 13])];
|
||||
state[13] = g_sbox[buf1];
|
||||
|
||||
/* Row 2 */
|
||||
|
||||
buf1 = state[2] ^ expanded_key[(round * 16) + 2];
|
||||
buf2 = state[6] ^ expanded_key[(round * 16) + 6];
|
||||
state[2] = g_sbox[(state[10] ^ expanded_key[(round * 16) + 10])];
|
||||
state[6] = g_sbox[(state[14] ^ expanded_key[(round * 16) + 14])];
|
||||
state[10] = g_sbox[buf1];
|
||||
state[14] = g_sbox[buf2];
|
||||
|
||||
/* Row 3 */
|
||||
|
||||
buf1 = state[15] ^ expanded_key[(round * 16) + 15];
|
||||
state[15] = g_sbox[(state[11] ^ expanded_key[(round * 16) + 11])];
|
||||
state[11] = g_sbox[(state[7] ^ expanded_key[(round * 16) + 7])];
|
||||
state[7] = g_sbox[(state[3] ^ expanded_key[(round * 16) + 3])];
|
||||
state[3] = g_sbox[buf1];
|
||||
|
||||
/* mixcolums */
|
||||
/* Col1 */
|
||||
|
||||
buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
|
||||
buf2 = state[0];
|
||||
buf3 = state[0] ^ state[1]; buf3 = galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
|
||||
buf3 = state[1] ^ state[2]; buf3 = galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
|
||||
buf3 = state[2] ^ state[3]; buf3 = galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
|
||||
buf3 = state[3] ^ buf2; buf3 = galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col2 */
|
||||
|
||||
buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
|
||||
buf2 = state[4];
|
||||
buf3 = state[4] ^ state[5]; buf3 = galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
|
||||
buf3 = state[5] ^ state[6]; buf3 = galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
|
||||
buf3 = state[6] ^ state[7]; buf3 = galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
|
||||
buf3 = state[7] ^ buf2; buf3 = galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col3 */
|
||||
|
||||
buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
|
||||
buf2 = state[8];
|
||||
buf3 = state[8] ^ state[9]; buf3 = galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
|
||||
buf3 = state[9] ^ state[10]; buf3 = galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
|
||||
buf3 = state[10] ^ state[11]; buf3 = galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
|
||||
buf3 = state[11] ^ buf2; buf3 = galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col4 */
|
||||
|
||||
buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
|
||||
buf2 = state[12];
|
||||
buf3 = state[12] ^ state[13]; buf3 = galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
|
||||
buf3 = state[13] ^ state[14]; buf3 = galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
|
||||
buf3 = state[14] ^ state[15]; buf3 = galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
|
||||
buf3 = state[15] ^ buf2; buf3 = galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
|
||||
}
|
||||
|
||||
/* 10th round without mixcols */
|
||||
|
||||
state[0] = g_sbox[(state[0] ^ expanded_key[(round * 16)])];
|
||||
state[4] = g_sbox[(state[4] ^ expanded_key[(round * 16) + 4])];
|
||||
state[8] = g_sbox[(state[8] ^ expanded_key[(round * 16) + 8])];
|
||||
state[12] = g_sbox[(state[12] ^ expanded_key[(round * 16) + 12])];
|
||||
|
||||
/* Row 1 */
|
||||
|
||||
buf1 = state[1] ^ expanded_key[(round * 16) + 1];
|
||||
state[1] = g_sbox[(state[5] ^ expanded_key[(round * 16) + 5])];
|
||||
state[5] = g_sbox[(state[9] ^ expanded_key[(round * 16) + 9])];
|
||||
state[9] = g_sbox[(state[13] ^ expanded_key[(round * 16) + 13])];
|
||||
state[13] = g_sbox[buf1];
|
||||
|
||||
/* Row 2 */
|
||||
|
||||
buf1 = state[2] ^ expanded_key[(round * 16) + 2];
|
||||
buf2 = state[6] ^ expanded_key[(round * 16) + 6];
|
||||
state[2] = g_sbox[(state[10] ^ expanded_key[(round * 16) + 10])];
|
||||
state[6] = g_sbox[(state[14] ^ expanded_key[(round * 16) + 14])];
|
||||
state[10] = g_sbox[buf1];
|
||||
state[14] = g_sbox[buf2];
|
||||
|
||||
/* Row 3 */
|
||||
|
||||
buf1 = state[15] ^ expanded_key[(round * 16) + 15];
|
||||
state[15] = g_sbox[(state[11] ^ expanded_key[(round * 16) + 11])];
|
||||
state[11] = g_sbox[(state[7] ^ expanded_key[(round * 16) + 7])];
|
||||
state[7] = g_sbox[(state[3] ^ expanded_key[(round * 16) + 3])];
|
||||
state[3] = g_sbox[buf1];
|
||||
|
||||
/* Last addroundkey */
|
||||
|
||||
state[0] ^= expanded_key[160];
|
||||
state[1] ^= expanded_key[161];
|
||||
state[2] ^= expanded_key[162];
|
||||
state[3] ^= expanded_key[163];
|
||||
state[4] ^= expanded_key[164];
|
||||
state[5] ^= expanded_key[165];
|
||||
state[6] ^= expanded_key[166];
|
||||
state[7] ^= expanded_key[167];
|
||||
state[8] ^= expanded_key[168];
|
||||
state[9] ^= expanded_key[169];
|
||||
state[10] ^= expanded_key[170];
|
||||
state[11] ^= expanded_key[171];
|
||||
state[12] ^= expanded_key[172];
|
||||
state[13] ^= expanded_key[173];
|
||||
state[14] ^= expanded_key[174];
|
||||
state[15] ^= expanded_key[175];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Name: aes_decr
|
||||
*
|
||||
* Description:
|
||||
* Internal implementation of AES128 decryption.
|
||||
* Straight forward aes decryption implementation. The order of substeps is
|
||||
* the exact reverse of decryption inverse functions:
|
||||
*
|
||||
* - addRoundKey is its own inverse
|
||||
* - rsbox is inverse of sbox
|
||||
* - rightshift instead of leftshift
|
||||
* - invMixColumns = barreto + mixColumns
|
||||
*
|
||||
* No further subfunctions to save cycles for function calls no structuring
|
||||
* with "for (....)" to save cycles
|
||||
*
|
||||
* Input Parameters:
|
||||
* expanded_key expanded AES128 key
|
||||
* state 16 bytes of cipher text and plain text
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void aes_decr(FAR uint8_t *state, FAR const uint8_t *expanded_key)
|
||||
{
|
||||
uint8_t buf1;
|
||||
uint8_t buf2;
|
||||
uint8_t buf3;
|
||||
int8_t round;
|
||||
|
||||
round = 9;
|
||||
|
||||
/* Initial addroundkey */
|
||||
|
||||
state[0] ^= expanded_key[160];
|
||||
state[1] ^= expanded_key[161];
|
||||
state[2] ^= expanded_key[162];
|
||||
state[3] ^= expanded_key[163];
|
||||
state[4] ^= expanded_key[164];
|
||||
state[5] ^= expanded_key[165];
|
||||
state[6] ^= expanded_key[166];
|
||||
state[7] ^= expanded_key[167];
|
||||
state[8] ^= expanded_key[168];
|
||||
state[9] ^= expanded_key[169];
|
||||
state[10] ^= expanded_key[170];
|
||||
state[11] ^= expanded_key[171];
|
||||
state[12] ^= expanded_key[172];
|
||||
state[13] ^= expanded_key[173];
|
||||
state[14] ^= expanded_key[174];
|
||||
state[15] ^= expanded_key[175];
|
||||
|
||||
/* 10th round without mixcols */
|
||||
|
||||
state[0] = g_rsbox[state[0]] ^ expanded_key[(round * 16)];
|
||||
state[4] = g_rsbox[state[4]] ^ expanded_key[(round * 16) + 4];
|
||||
state[8] = g_rsbox[state[8]] ^ expanded_key[(round * 16) + 8];
|
||||
state[12] = g_rsbox[state[12]] ^ expanded_key[(round * 16) + 12];
|
||||
|
||||
/* Row 1 */
|
||||
|
||||
buf1 = g_rsbox[state[13]] ^ expanded_key[(round * 16) + 1];
|
||||
state[13] = g_rsbox[state[9]] ^ expanded_key[(round * 16) + 13];
|
||||
state[9] = g_rsbox[state[5]] ^ expanded_key[(round * 16) + 9];
|
||||
state[5] = g_rsbox[state[1]] ^ expanded_key[(round * 16) + 5];
|
||||
state[1] = buf1;
|
||||
|
||||
/* Row 2 */
|
||||
|
||||
buf1 = g_rsbox[state[2]] ^ expanded_key[(round * 16) + 10];
|
||||
buf2 = g_rsbox[state[6]] ^ expanded_key[(round * 16) + 14];
|
||||
state[2] = g_rsbox[state[10]] ^ expanded_key[(round * 16) + 2];
|
||||
state[6] = g_rsbox[state[14]] ^ expanded_key[(round * 16) + 6];
|
||||
state[10] = buf1;
|
||||
state[14] = buf2;
|
||||
|
||||
/* Row 3 */
|
||||
|
||||
buf1 = g_rsbox[state[3]] ^ expanded_key[(round * 16) + 15];
|
||||
state[3] = g_rsbox[state[7]] ^ expanded_key[(round * 16) + 3];
|
||||
state[7] = g_rsbox[state[11]] ^ expanded_key[(round * 16) + 7];
|
||||
state[11] = g_rsbox[state[15]] ^ expanded_key[(round * 16) + 11];
|
||||
state[15] = buf1;
|
||||
|
||||
for (round = 8; round >= 0; round--)
|
||||
{
|
||||
/* barreto */
|
||||
/* Col1 */
|
||||
|
||||
buf1 = galois_mul2(galois_mul2(state[0] ^ state[2]));
|
||||
buf2 = galois_mul2(galois_mul2(state[1] ^ state[3]));
|
||||
state[0] ^= buf1;
|
||||
state[1] ^= buf2;
|
||||
state[2] ^= buf1;
|
||||
state[3] ^= buf2;
|
||||
|
||||
/* Col2 */
|
||||
|
||||
buf1 = galois_mul2(galois_mul2(state[4] ^ state[6]));
|
||||
buf2 = galois_mul2(galois_mul2(state[5] ^ state[7]));
|
||||
state[4] ^= buf1;
|
||||
state[5] ^= buf2;
|
||||
state[6] ^= buf1;
|
||||
state[7] ^= buf2;
|
||||
|
||||
/* Col3 */
|
||||
|
||||
buf1 = galois_mul2(galois_mul2(state[8] ^ state[10]));
|
||||
buf2 = galois_mul2(galois_mul2(state[9] ^ state[11]));
|
||||
state[8] ^= buf1;
|
||||
state[9] ^= buf2;
|
||||
state[10] ^= buf1;
|
||||
state[11] ^= buf2;
|
||||
|
||||
/* Col4 */
|
||||
|
||||
buf1 = galois_mul2(galois_mul2(state[12] ^ state[14]));
|
||||
buf2 = galois_mul2(galois_mul2(state[13] ^ state[15]));
|
||||
state[12] ^= buf1;
|
||||
state[13] ^= buf2;
|
||||
state[14] ^= buf1;
|
||||
state[15] ^= buf2;
|
||||
|
||||
/* mixcolums */
|
||||
/* Col1 */
|
||||
|
||||
buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
|
||||
buf2 = state[0];
|
||||
buf3 = state[0] ^ state[1]; buf3 = galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
|
||||
buf3 = state[1] ^ state[2]; buf3 = galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
|
||||
buf3 = state[2] ^ state[3]; buf3 = galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
|
||||
buf3 = state[3] ^ buf2; buf3 = galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col2 */
|
||||
|
||||
buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
|
||||
buf2 = state[4];
|
||||
buf3 = state[4] ^ state[5]; buf3 = galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
|
||||
buf3 = state[5] ^ state[6]; buf3 = galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
|
||||
buf3 = state[6] ^ state[7]; buf3 = galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
|
||||
buf3 = state[7] ^ buf2; buf3 = galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col3 */
|
||||
|
||||
buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
|
||||
buf2 = state[8];
|
||||
buf3 = state[8] ^ state[9]; buf3 = galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
|
||||
buf3 = state[9] ^ state[10]; buf3 = galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
|
||||
buf3 = state[10] ^ state[11]; buf3 = galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
|
||||
buf3 = state[11] ^ buf2; buf3 = galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
|
||||
|
||||
/* Col4 */
|
||||
|
||||
buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
|
||||
buf2 = state[12];
|
||||
buf3 = state[12] ^ state[13]; buf3 = galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
|
||||
buf3 = state[13] ^ state[14]; buf3 = galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
|
||||
buf3 = state[14] ^ state[15]; buf3 = galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
|
||||
buf3 = state[15] ^ buf2; buf3 = galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
|
||||
|
||||
/* addroundkey, rsbox and shiftrows */
|
||||
/* Row 0 */
|
||||
|
||||
state[0] = g_rsbox[state[0]] ^ expanded_key[(round * 16)];
|
||||
state[4] = g_rsbox[state[4]] ^ expanded_key[(round * 16) + 4];
|
||||
state[8] = g_rsbox[state[8]] ^ expanded_key[(round * 16) + 8];
|
||||
state[12] = g_rsbox[state[12]] ^ expanded_key[(round * 16) + 12];
|
||||
|
||||
/* Row 1 */
|
||||
|
||||
buf1 = g_rsbox[state[13]] ^ expanded_key[(round * 16) + 1];
|
||||
state[13] = g_rsbox[state[9]] ^ expanded_key[(round * 16) + 13];
|
||||
state[9] = g_rsbox[state[5]] ^ expanded_key[(round * 16) + 9];
|
||||
state[5] = g_rsbox[state[1]] ^ expanded_key[(round * 16) + 5];
|
||||
state[1] = buf1;
|
||||
|
||||
/* Row 2 */
|
||||
|
||||
buf1 = g_rsbox[state[2]] ^ expanded_key[(round * 16) + 10];
|
||||
buf2 = g_rsbox[state[6]] ^ expanded_key[(round * 16) + 14];
|
||||
state[2] = g_rsbox[state[10]] ^ expanded_key[(round * 16) + 2];
|
||||
state[6] = g_rsbox[state[14]] ^ expanded_key[(round * 16) + 6];
|
||||
state[10] = buf1;
|
||||
state[14] = buf2;
|
||||
|
||||
/* Row 3 */
|
||||
|
||||
buf1 = g_rsbox[state[3]] ^ expanded_key[(round * 16) + 15];
|
||||
state[3] = g_rsbox[state[7]] ^ expanded_key[(round * 16) + 3];
|
||||
state[7] = g_rsbox[state[11]] ^ expanded_key[(round * 16) + 7];
|
||||
state[11] = g_rsbox[state[15]] ^ expanded_key[(round * 16) + 11];
|
||||
state[15] = buf1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: aes_encrypt
|
||||
*
|
||||
* Description:
|
||||
* AES128 encryption: Given AES128 key and 16 bytes plain text, cipher
|
||||
* text of 16 bytes is computed. The AES implementation is in mode ECB
|
||||
* (Electronic Code Book).
|
||||
*
|
||||
* Input Parameters:
|
||||
* key AES128 key of size 16 bytes
|
||||
* state 16 bytes of plain text and cipher text
|
||||
*
|
||||
* Returned Value
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void aes_encrypt(FAR uint8_t *state, FAR const uint8_t *key)
|
||||
{
|
||||
/* Expand the key into 176 bytes */
|
||||
|
||||
expand_key(g_expanded_key, key);
|
||||
aes_encr(state, g_expanded_key);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: aes_decrypt
|
||||
*
|
||||
* Description:
|
||||
* AES128 decryption: Given AES128 key and 16 bytes cipher text, plain
|
||||
* text of 16 bytes is computed The AES implementation is in mode ECB
|
||||
* (Electronic Code Book).
|
||||
*
|
||||
* Input Parameters:
|
||||
* key AES128 key of size 16 bytes
|
||||
* state 16 bytes of plain text and cipher text
|
||||
*
|
||||
* Returned Value
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void aes_decrypt(FAR uint8_t *state, FAR const uint8_t *key)
|
||||
{
|
||||
/* Expand the key into 176 bytes */
|
||||
|
||||
expand_key(g_expanded_key, key);
|
||||
aes_decr(state, g_expanded_key);
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ int up_cryptoinitialize(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_CRYPTO_ALGTEST
|
||||
#ifdef CONFIG_CRYPTO_ALGTEST
|
||||
res = crypto_test();
|
||||
if (res)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,16 @@
|
|||
#include <nuttx/crypto/crypto.h>
|
||||
#include <nuttx/crypto/cryptodev.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CRYPTO_AES
|
||||
# define AES_CYPHER(mode) \
|
||||
aes_cypher(op->dst, op->src, op->len, op->iv, ses->key, ses->keylen, \
|
||||
mode, encrypt)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
|
@ -69,13 +79,18 @@ static int cryptodev_ioctl(FAR struct file *filep, int cmd,
|
|||
|
||||
static const struct file_operations g_cryptodevops =
|
||||
{
|
||||
0, /* open */
|
||||
0, /* close */
|
||||
cryptodev_read, /* read */
|
||||
cryptodev_write, /* write */
|
||||
0, /* seek */
|
||||
cryptodev_ioctl, /* ioctl */
|
||||
0, /* poll */
|
||||
0, /* open */
|
||||
0, /* close */
|
||||
cryptodev_read, /* read */
|
||||
cryptodev_write, /* write */
|
||||
0, /* seek */
|
||||
cryptodev_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, 0 /* poll */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
, 0 /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -96,11 +111,11 @@ static ssize_t cryptodev_write(FAR struct file *filep, FAR const char *buffer,
|
|||
|
||||
static int cryptodev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
switch(cmd)
|
||||
switch (cmd)
|
||||
{
|
||||
case CIOCGSESSION:
|
||||
{
|
||||
struct session_op *ses = (struct session_op*)arg;
|
||||
FAR struct session_op *ses = (FAR struct session_op *)arg;
|
||||
ses->ses = (uint32_t)ses;
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -110,51 +125,46 @@ static int cryptodev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
return OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CRYPTO_AES
|
||||
case CIOCCRYPT:
|
||||
{
|
||||
FAR struct crypt_op *op = (struct crypt_op*)arg;
|
||||
FAR struct session_op *ses = (struct session_op*)op->ses;
|
||||
FAR struct crypt_op *op = (FAR struct crypt_op *)arg;
|
||||
FAR struct session_op *ses = (FAR struct session_op *)op->ses;
|
||||
int encrypt;
|
||||
|
||||
switch (op->op)
|
||||
{
|
||||
case COP_ENCRYPT:
|
||||
encrypt = 1;
|
||||
break;
|
||||
{
|
||||
case COP_ENCRYPT:
|
||||
encrypt = 1;
|
||||
break;
|
||||
|
||||
case COP_DECRYPT:
|
||||
encrypt = 0;
|
||||
break;
|
||||
case COP_DECRYPT:
|
||||
encrypt = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (ses->cipher)
|
||||
{
|
||||
{
|
||||
case CRYPTO_AES_ECB:
|
||||
return AES_CYPHER(AES_MODE_ECB);
|
||||
|
||||
#if defined(CONFIG_CRYPTO_AES)
|
||||
# define AES_CYPHER(mode) aes_cypher(op->dst, op->src, op->len, op->iv, ses->key, ses->keylen, mode, encrypt)
|
||||
case CRYPTO_AES_CBC:
|
||||
return AES_CYPHER(AES_MODE_CBC);
|
||||
|
||||
case CRYPTO_AES_ECB:
|
||||
return AES_CYPHER(AES_MODE_ECB);
|
||||
case CRYPTO_AES_CTR:
|
||||
return AES_CYPHER(AES_MODE_CTR);
|
||||
|
||||
case CRYPTO_AES_CBC:
|
||||
return AES_CYPHER(AES_MODE_CBC);
|
||||
|
||||
case CRYPTO_AES_CTR:
|
||||
return AES_CYPHER(AES_MODE_CTR);
|
||||
|
||||
# undef AES_CYPHER
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@
|
|||
|
||||
#include "testmngr.h"
|
||||
|
||||
/*****************************************************************************
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
*****************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int do_test_aes(FAR struct cipher_testvec* test, int mode, int encrypt)
|
||||
static int do_test_aes(FAR struct cipher_testvec *test, int mode, int encrypt)
|
||||
{
|
||||
FAR void *out = kmm_zalloc(test->rlen);
|
||||
|
||||
|
|
|
|||
168
drivers/Kconfig
168
drivers/Kconfig
|
|
@ -11,6 +11,9 @@ config DISABLE_POLL
|
|||
supported. If you do not use poll() or select(), then you can
|
||||
select DISABLE_POLL to reduce the code footprint by a small amount.
|
||||
|
||||
This selection disables the poll() interface as well as interfaces
|
||||
the derive from poll() such as select().
|
||||
|
||||
config DEV_NULL
|
||||
bool "Enable /dev/null"
|
||||
default y
|
||||
|
|
@ -27,13 +30,7 @@ config DEV_RANDOM
|
|||
default n
|
||||
depends on ARCH_HAVE_RNG
|
||||
|
||||
config LOOP
|
||||
bool "Enable loop device"
|
||||
default n
|
||||
---help---
|
||||
Supports the standard loop device that can be used to export a
|
||||
file (or character device) as a block device. See losetup() and
|
||||
loteardown() in include/nuttx/fs/fs.h.
|
||||
source drivers/loop/Kconfig
|
||||
|
||||
menu "Buffering"
|
||||
|
||||
|
|
@ -107,6 +104,20 @@ config CAN_EXTID
|
|||
Enables support for the 28-bit extended ID. Default Standard 11-bit
|
||||
IDs.
|
||||
|
||||
config ARCH_HAVE_CAN_ERRORS
|
||||
bool
|
||||
default n
|
||||
|
||||
config CAN_ERRORS
|
||||
bool "CAN error reporting"
|
||||
default n
|
||||
depends on ARCH_HAVE_CAN_ERRORS
|
||||
---help---
|
||||
Support CAN error reporting. If this option is selected then CAN
|
||||
error reporting is enabled. In the event of an error, the ch_error
|
||||
bit will be set in the CAN message and the following message payload
|
||||
will include a more detailed description of certain errors.
|
||||
|
||||
config CAN_FD
|
||||
bool "CAN FD"
|
||||
default n
|
||||
|
|
@ -125,6 +136,70 @@ config CAN_NPENDINGRTR
|
|||
---help---
|
||||
The size of the list of pending RTR requests. Default: 4
|
||||
|
||||
config CAN_TXREADY
|
||||
bool "can_txready interface"
|
||||
default n
|
||||
select SCHED_WORKQUEUE
|
||||
---help---
|
||||
This selection enables the can_txready() interface. This interface
|
||||
is needed only for CAN hardware that supports queing of outgoing
|
||||
messages in a H/W FIFO.
|
||||
|
||||
The CAN upper half driver also supports a queue of output messages
|
||||
in a S/W FIFO. Messages are added to that queue when when
|
||||
can_write() is called and removed from the queue in can_txdone()
|
||||
when each TX message is complete.
|
||||
|
||||
After each message is added to the S/W FIFO, the CAN upper half
|
||||
driver will attempt to send the message by calling into the lower
|
||||
half driver. That send will not be performed if the lower half
|
||||
driver is busy, i.e., if dev_txready() returns false. In that
|
||||
case, the number of messages in the S/W FIFO can grow. If the
|
||||
S/W FIFO becomes full, then can_write() will wait for space in
|
||||
the S/W FIFO.
|
||||
|
||||
If the CAN hardware does not support a H/W FIFO then busy means
|
||||
that the hardware is actively sending the message and is
|
||||
guaranteed to become non busy (i.e, dev_txready()) when the
|
||||
send transfer completes and can_txdone() is called. So the call
|
||||
to can_txdone() means that the transfer has completed and also
|
||||
that the hardware is ready to accept another transfer.
|
||||
|
||||
If the CAN hardware supports a H/W FIFO, can_txdone() is not
|
||||
called when the tranfer is complete, but rather when the
|
||||
transfer is queued in the H/W FIFO. When the H/W FIFO becomes
|
||||
full, then dev_txready() will report false and the number of
|
||||
queued messages in the S/W FIFO will grow.
|
||||
|
||||
There is no mechanism in this case to inform the upper half
|
||||
driver when the hardware is again available, when there is
|
||||
again space in the H/W FIFO. can_txdone() will not be called
|
||||
again. If the S/W FIFO becomes full, then the upper half
|
||||
driver will wait for space to become available, but there is
|
||||
no event to awaken it and the driver will hang.
|
||||
|
||||
Enabling this feature adds support for the can_txready()
|
||||
interface. This function is called from the lower half
|
||||
driver's CAN interrupt handler each time a TX transfer
|
||||
completes. This is a sure indication that the H/W FIFO is
|
||||
no longer full. can_txready() will then awaken the
|
||||
can_write() logic and the hang condition is avoided.
|
||||
|
||||
choice
|
||||
prompt "TX Ready Work Queue"
|
||||
default CAN_TXREADY_HIPRI
|
||||
depends on CAN_TXREADY
|
||||
|
||||
config CAN_TXREADY_LOPRI
|
||||
bool "Low-priority work queue"
|
||||
select SCHED_LPWORK
|
||||
|
||||
config CAN_TXREADY_HIPRI
|
||||
bool "High-priority work queue"
|
||||
select SCHED_HPWORK
|
||||
|
||||
endchoice # TX Ready Work Queue
|
||||
|
||||
config CAN_LOOPBACK
|
||||
bool "CAN loopback mode"
|
||||
default n
|
||||
|
|
@ -139,6 +214,10 @@ config ARCH_HAVE_PWM_PULSECOUNT
|
|||
bool
|
||||
default n
|
||||
|
||||
config ARCH_HAVE_PWM_MULTICHAN
|
||||
bool
|
||||
default n
|
||||
|
||||
menuconfig PWM
|
||||
bool "PWM Driver Support"
|
||||
default n
|
||||
|
|
@ -147,6 +226,7 @@ menuconfig PWM
|
|||
See include/nuttx/pwm.h for further PWM driver information.
|
||||
|
||||
if PWM
|
||||
|
||||
config PWM_PULSECOUNT
|
||||
bool "PWM Pulse Count Support"
|
||||
default n
|
||||
|
|
@ -157,6 +237,26 @@ config PWM_PULSECOUNT
|
|||
hardware will support a fixed pulse count, then this configuration
|
||||
should be set to enable the capability.
|
||||
|
||||
config PWM_MULTICHAN
|
||||
bool "PWM Multiple Output Channel Support"
|
||||
default n
|
||||
depends on ARCH_HAVE_PWM_MULTICHAN
|
||||
depends on !PWM_PULSECOUNT
|
||||
---help---
|
||||
Enables support for multiple output channels per timer.
|
||||
|
||||
if PWM_MULTICHAN
|
||||
|
||||
config PWM_NCHANNELS
|
||||
int "Number of Output Channels Per Timer"
|
||||
default 1
|
||||
range 1 4
|
||||
---help---
|
||||
Specifies the number of output channels per timer. Each timer
|
||||
may support fewer output channels than this value.
|
||||
|
||||
endif # PWM_MULTICHAN
|
||||
|
||||
endif # PWM
|
||||
|
||||
config ARCH_HAVE_I2CRESET
|
||||
|
|
@ -168,41 +268,11 @@ menuconfig I2C
|
|||
default n
|
||||
---help---
|
||||
This selection enables building of the "upper-half" I2C driver.
|
||||
See include/nuttx/i2c.h for further I2C driver information.
|
||||
See include/nuttx/i2c/i2c_master.h for further I2C driver information.
|
||||
|
||||
if I2C
|
||||
|
||||
config I2C_SLAVE
|
||||
bool "I2C Slave"
|
||||
default n
|
||||
|
||||
config I2C_TRANSFER
|
||||
bool "Support the I2C transfer() method"
|
||||
default n
|
||||
|
||||
config I2C_WRITEREAD
|
||||
bool "Support the I2C writeread() method"
|
||||
default n
|
||||
|
||||
config I2C_POLLED
|
||||
bool "Polled I2C (no interrupts)"
|
||||
default n
|
||||
|
||||
config I2C_TRACE
|
||||
bool "Enable I2C trace debug"
|
||||
default n
|
||||
|
||||
config I2C_NTRACE
|
||||
int "Number of I2C trace records"
|
||||
default 32
|
||||
depends on I2C_TRACE
|
||||
|
||||
config I2C_RESET
|
||||
bool "Support up_i2creset"
|
||||
default n
|
||||
depends on ARCH_HAVE_I2CRESET
|
||||
|
||||
endif # I2C
|
||||
source drivers/i2c/Kconfig
|
||||
endif
|
||||
|
||||
menuconfig SPI
|
||||
bool "SPI Driver Support"
|
||||
|
|
@ -293,7 +363,7 @@ source drivers/input/Kconfig
|
|||
endif # INPUT
|
||||
|
||||
menuconfig IOEXPANDER
|
||||
bool "IO Expanders Support"
|
||||
bool "IO Expander Support"
|
||||
default n
|
||||
---help---
|
||||
This directory holds implementations of IO expander drivers.
|
||||
|
|
@ -319,6 +389,8 @@ if LCD
|
|||
source drivers/lcd/Kconfig
|
||||
endif # LCD
|
||||
|
||||
source drivers/leds/Kconfig
|
||||
|
||||
menuconfig MMCSD
|
||||
bool "MMC/SD Driver Support"
|
||||
default n
|
||||
|
|
@ -331,6 +403,16 @@ if MMCSD
|
|||
source drivers/mmcsd/Kconfig
|
||||
endif # MMCSD
|
||||
|
||||
menuconfig MODEM
|
||||
bool "Modem Support"
|
||||
default n
|
||||
---help---
|
||||
Enable modem support.
|
||||
|
||||
if MODEM
|
||||
source drivers/modem/Kconfig
|
||||
endif # MODEM
|
||||
|
||||
menuconfig MTD
|
||||
bool "Memory Technology Device (MTD) Support"
|
||||
default n
|
||||
|
|
@ -468,15 +550,13 @@ if USBHOST
|
|||
source drivers/usbhost/Kconfig
|
||||
endif # USBHOST
|
||||
|
||||
menuconfig WIRELESS
|
||||
menuconfig DRIVERS_WIRELESS
|
||||
bool "Wireless Device Support"
|
||||
default n
|
||||
---help---
|
||||
Drivers for various wireless devices.
|
||||
|
||||
if WIRELESS
|
||||
source drivers/wireless/Kconfig
|
||||
endif # WIRELESS
|
||||
|
||||
comment "System Logging Device Options"
|
||||
|
||||
|
|
|
|||
|
|
@ -52,10 +52,14 @@ VPATH = .
|
|||
include analog$(DELIM)Make.defs
|
||||
include audio$(DELIM)Make.defs
|
||||
include bch$(DELIM)Make.defs
|
||||
include i2c$(DELIM)Make.defs
|
||||
include input$(DELIM)Make.defs
|
||||
include ioexpander$(DELIM)Make.defs
|
||||
include lcd$(DELIM)Make.defs
|
||||
include leds$(DELIM)Make.defs
|
||||
include loop$(DELIM)Make.defs
|
||||
include mmcsd$(DELIM)Make.defs
|
||||
include modem$(DELIM)Make.defs
|
||||
include mtd$(DELIM)Make.defs
|
||||
include eeprom$(DELIM)Make.defs
|
||||
include net$(DELIM)Make.defs
|
||||
|
|
@ -76,7 +80,7 @@ ifneq ($(CONFIG_NFILE_DESCRIPTORS),0)
|
|||
CSRCS += dev_null.c dev_zero.c
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
|
||||
CSRCS += ramdisk.c loop.c
|
||||
CSRCS += ramdisk.c
|
||||
ifeq ($(CONFIG_DRVR_WRITEBUFFER),y)
|
||||
CSRCS += rwbuffer.c
|
||||
else
|
||||
|
|
|
|||
|
|
@ -21,11 +21,6 @@ dev_null.c and dev_zero.c
|
|||
want to register these devices (devnull_register() and
|
||||
devzero_register()).
|
||||
|
||||
loop.c
|
||||
Supports the standard loop device that can be used to export a
|
||||
file (or character device) as a block device. See losetup() and
|
||||
loteardown() in include/nuttx/fs/fs.h.
|
||||
|
||||
pwm.c
|
||||
Provides the "upper half" of a pulse width modulation (PWM) driver.
|
||||
The "lower half" of the PWM driver is provided by device-specific
|
||||
|
|
@ -36,18 +31,10 @@ ramdisk.c
|
|||
a block driver that can be mounted as a files system. See
|
||||
include/nuttx/fs/ramdisk.h.
|
||||
|
||||
timer.c
|
||||
Provides the "upper half" for a generic timer driver. See
|
||||
include/nuttx/timers/timer.h for more information.
|
||||
|
||||
rwbuffer.c
|
||||
A facility that can be use by any block driver in-order to add
|
||||
writing buffering and read-ahead buffering.
|
||||
|
||||
watchdog.c
|
||||
Provides the "upper half" for a generic watchdog driver. See
|
||||
include/nuttx/timers/watchdog.h for more information.
|
||||
|
||||
Subdirectories of this directory:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -81,6 +68,9 @@ eeprom/
|
|||
interface but instead use the simple character interface provided by
|
||||
the EEPROM drivers.
|
||||
|
||||
i2c/
|
||||
I2C drivers and support logic. See include/nuttx/i2c/i2c_master.h
|
||||
|
||||
input/
|
||||
This directory holds implementations of human input device (HID)
|
||||
drivers. This includes such things as mouse, touchscreen, joystick,
|
||||
|
|
@ -94,6 +84,15 @@ lcd/
|
|||
Drivers for parallel and serial LCD and OLED type devices. These
|
||||
drivers support interfaces as defined in include/nuttx/lcd/lcd.h
|
||||
|
||||
leds/
|
||||
Various LED-related drivers including discrete as well as PWM-
|
||||
driven LEDs.
|
||||
|
||||
loop/
|
||||
Supports the standard loop device that can be used to export a
|
||||
file (or character device) as a block device. See losetup() and
|
||||
loteardown() in include/nuttx/fs/fs.h.
|
||||
|
||||
mmcsd/
|
||||
Support for MMC/SD block drivers. MMC/SD block drivers based on
|
||||
SPI and SDIO/MCI interfaces are supported. See include/nuttx/mmcsd.h
|
||||
|
|
@ -148,11 +147,22 @@ serial/
|
|||
the NuttX system console. See also include/nuttx/serial/serial.h
|
||||
|
||||
spi/
|
||||
SPI drivers. See include/nuttx/spi.h
|
||||
SPI drivers and support logic. See include/nuttx/spi/spi.h
|
||||
|
||||
syslog/
|
||||
System logging devices. See include/syslog.h and include/nuttx/syslog/syslog.h
|
||||
|
||||
timers/
|
||||
Includes support for various timer devices including:
|
||||
|
||||
- An "upper half" for a generic timer driver. See
|
||||
include/nuttx/timers/timer.h for more information.
|
||||
|
||||
- An "upper half" for a generic watchdog driver. See
|
||||
include/nuttx/timers/watchdog.h for more information.
|
||||
|
||||
- RTC drivers
|
||||
|
||||
usbdev/
|
||||
USB device drivers. See also include/nuttx/usb/usbdev.h
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,18 @@ config ADC_NO_STARTUP_CONV
|
|||
---help---
|
||||
Do not start conversion when opening ADC device.
|
||||
|
||||
config ADC_ADS1242
|
||||
bool "TI ADS1242 support"
|
||||
default n
|
||||
select SPI
|
||||
---help---
|
||||
Enable driver support for the ADS1242 24-Bit SPI powered ADC.
|
||||
|
||||
This driver supports reading the ADC conversion result as well as
|
||||
configuring the ADC, setting the input channel, etc. is implemented
|
||||
via ioctl calls. However, it does not yet implement the standard ADC
|
||||
interface.
|
||||
|
||||
config ADC_ADS125X
|
||||
bool "TI ADS1255/ADS1256 support"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ endif
|
|||
|
||||
# Include ADC device drivers
|
||||
|
||||
ifeq ($(CONFIG_ADC_ADS1242),y)
|
||||
CSRCS += ads1242.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADC_ADS125X),y)
|
||||
CSRCS += ads1255.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ static int dac_setup(FAR struct dac_dev_s *dev)
|
|||
FAR struct spi_dev_s *spi = priv->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_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);
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -167,10 +167,10 @@ 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;
|
||||
|
||||
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, 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_txdone(&g_dacdev);
|
||||
return 0;
|
||||
|
|
@ -207,8 +207,8 @@ FAR struct dac_dev_s *up_ad5410initialize(FAR struct spi_dev_s *spi,
|
|||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_dacdev.ad_priv;
|
||||
|
||||
priv->spi=spi;
|
||||
priv->devno=devno;
|
||||
priv->spi = spi;
|
||||
priv->devno = devno;
|
||||
return &g_dacdev;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <nuttx/analog/adc.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
|
|
@ -67,8 +67,9 @@
|
|||
|
||||
static int adc_open(FAR struct file *filep);
|
||||
static int adc_close(FAR struct file *filep);
|
||||
static ssize_t adc_read(FAR struct file *, FAR char *, size_t);
|
||||
static int adc_ioctl(FAR struct file *filep,int cmd,unsigned long arg);
|
||||
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);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
|
@ -133,7 +134,7 @@ static int adc_open(FAR struct file *filep)
|
|||
{
|
||||
/* Yes.. perform one time hardware initialization. */
|
||||
|
||||
irqstate_t flags = irqsave();
|
||||
irqstate_t flags = enter_critical_section();
|
||||
ret = dev->ad_ops->ao_setup(dev);
|
||||
if (ret == OK)
|
||||
{
|
||||
|
|
@ -151,7 +152,7 @@ static int adc_open(FAR struct file *filep)
|
|||
dev->ad_ocount = tmp;
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,9 +201,9 @@ static int adc_close(FAR struct file *filep)
|
|||
|
||||
/* Free the IRQ and disable the ADC device */
|
||||
|
||||
flags = irqsave(); /* Disable interrupts */
|
||||
flags = enter_critical_section(); /* Disable interrupts */
|
||||
dev->ad_ops->ao_shutdown(dev); /* Disable the ADC */
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
sem_post(&dev->ad_closesem);
|
||||
}
|
||||
|
|
@ -243,7 +244,7 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
|||
{
|
||||
/* Interrupts must be disabled while accessing the ad_recv FIFO */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
while (dev->ad_recv.af_head == dev->ad_recv.af_tail)
|
||||
{
|
||||
/* The receive FIFO is empty -- was non-blocking mode selected? */
|
||||
|
|
@ -339,7 +340,7 @@ static ssize_t adc_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
|
|||
ret = nread;
|
||||
|
||||
return_with_irqdisabled:
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
avdbg("Returning: %d\n", ret);
|
||||
|
|
|
|||
576
drivers/analog/ads1242.c
Normal file
576
drivers/analog/ads1242.c
Normal file
|
|
@ -0,0 +1,576 @@
|
|||
/****************************************************************************
|
||||
* drivers/sensors/ads1242.c
|
||||
* Character driver for the MCP3426 Differential Input 16 Bit Delta/Sigma ADC
|
||||
*
|
||||
* Copyright (C) 2015 DS-Automotion GmbH. All rights reserved.
|
||||
* Author: Alexander Entinger <a.entinger@ds-automotion.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <fixedmath.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/spi/spi.h>
|
||||
|
||||
#include <nuttx/analog/ads1242.h>
|
||||
|
||||
#if defined(CONFIG_SPI) && defined(CONFIG_ADC_ADS1242)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct ads1242_dev_s
|
||||
{
|
||||
FAR struct spi_dev_s *spi; /* Pointer to the SPI instance */
|
||||
uint32_t osc_period_us; /* Period of the oscillator attached to the ADS1242 in us */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* SPI Helpers */
|
||||
|
||||
static void ads1242_reset(FAR struct ads1242_dev_s *dev);
|
||||
static void ads1242_performSelfGainCalibration(
|
||||
FAR struct ads1242_dev_s *dev);
|
||||
static void ads1242_performSelfOffsetCalibration(
|
||||
FAR struct ads1242_dev_s *dev);
|
||||
static void 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);
|
||||
|
||||
static void ads1242_write_reg(FAR struct ads1242_dev_s *dev,
|
||||
uint8_t const reg_addr, uint8_t const reg_value);
|
||||
static void ads1242_read_reg(FAR struct ads1242_dev_s *dev,
|
||||
uint8_t const reg_addr, FAR uint8_t *reg_value);
|
||||
|
||||
static void ads1242_set_gain(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_GAIN_SELECTION const gain_selection);
|
||||
static void ads1242_set_positive_input(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_POSITIVE_INPUT_SELECTION const pos_in_sel);
|
||||
static void ads1242_set_negative_input(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_NEGATIVE_INPUT_SELECTION const neg_in_sel);
|
||||
static bool ads1242_is_data_ready(FAR struct ads1242_dev_s *dev);
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
static void ads1242_print_regs(FAR struct ads1242_dev_s *dev, char const *msg);
|
||||
#endif /* CONFIG_DEBUG && CONFIG_DEBUG_VERBOSE */
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
static int ads1242_open(FAR struct file *filep);
|
||||
static int ads1242_close(FAR struct file *filep);
|
||||
static ssize_t ads1242_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t ads1242_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
static int ads1242_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_ads1242_fops =
|
||||
{
|
||||
ads1242_open,
|
||||
ads1242_close,
|
||||
ads1242_read,
|
||||
ads1242_write,
|
||||
NULL,
|
||||
ads1242_ioctl
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_reset
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_reset(FAR struct ads1242_dev_s *dev)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_performSelfGainCalibration
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_performSelfGainCalibration(FAR struct ads1242_dev_s *dev)
|
||||
{
|
||||
SPI_SELECT(dev->spi, 0, true);
|
||||
|
||||
SPI_SEND(dev->spi, ADS1242_CMD_SELF_GAIN_CALIB);
|
||||
|
||||
SPI_SELECT(dev->spi, 0, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_performSelfOffsetCalibration
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_performSelfOffsetCalibration(FAR struct ads1242_dev_s *dev)
|
||||
{
|
||||
SPI_SELECT(dev->spi, 0, true);
|
||||
|
||||
SPI_SEND(dev->spi, ADS1242_CMD_SELF_OFFSET_CALIB);
|
||||
|
||||
SPI_SELECT(dev->spi, 0, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_performSystemOffsetCalibration
|
||||
****************************************************************************/
|
||||
|
||||
static void
|
||||
ads1242_performSystemOffsetCalibration(FAR struct ads1242_dev_s *dev)
|
||||
{
|
||||
SPI_SELECT(dev->spi, 0, true);
|
||||
|
||||
SPI_SEND(dev->spi, ADS1242_CMD_SYSTEM_OFFSET_CALIB);
|
||||
|
||||
SPI_SELECT(dev->spi, 0, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_read_conversion_result
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev,
|
||||
FAR uint32_t *conversion_result)
|
||||
{
|
||||
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:
|
||||
* RDATA, RDATAC, RREG, WREG: Min 50 x tOSC Periods
|
||||
*/
|
||||
|
||||
up_udelay(50 * dev->osc_period_us);
|
||||
|
||||
*conversion_result = 0;
|
||||
|
||||
/* 1st Byte = MSB
|
||||
* 2nd Byte = Mid-Byte
|
||||
* 3rd Byte = LSB
|
||||
*/
|
||||
|
||||
*conversion_result |= ((uint32_t)(SPI_SEND(dev->spi, 0xFF))) << 16;
|
||||
*conversion_result |= ((uint32_t)(SPI_SEND(dev->spi, 0xFF))) << 8;
|
||||
*conversion_result |= ((uint32_t)(SPI_SEND(dev->spi, 0xFF))) << 0;
|
||||
|
||||
SPI_SELECT(dev->spi, 0, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_write_reg
|
||||
*
|
||||
* Description:
|
||||
* Write to the registers starting with the register address specified as
|
||||
* part of the instruction. The number of registers that will be written
|
||||
* is one plus the value of the second byte.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_write_reg(FAR struct ads1242_dev_s *dev,
|
||||
uint8_t const reg_addr, uint8_t const reg_value)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_read_reg
|
||||
*
|
||||
* Description:
|
||||
* Output the data from up to 16 registers starting with the register
|
||||
* address specified as part of the instruction. The number of registers
|
||||
* read will be one plus the second byte count. If the count exceeds the
|
||||
* remaining registers, the addresses wrap back to the beginning.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_read_reg(FAR struct ads1242_dev_s *dev,
|
||||
uint8_t const reg_addr, FAR uint8_t *reg_value)
|
||||
{
|
||||
SPI_SELECT(dev->spi, 0, true);
|
||||
SPI_SEND(dev->spi, ADS1242_CMD_READ_REGISTER | reg_addr);
|
||||
SPI_SEND(dev->spi, 0x00); /* Read 1 Byte */
|
||||
|
||||
/* Delay between last SCLK edge for DIN and first SCLK edge for DOUT:
|
||||
* RDATA, RDATAC, RREG, WREG: Min 50 x tOSC Periods
|
||||
*/
|
||||
|
||||
up_udelay(50 * dev->osc_period_us);
|
||||
|
||||
*reg_value = SPI_SEND(dev->spi, 0xFF);
|
||||
|
||||
SPI_SELECT(dev->spi, 0, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_set_gain
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_set_gain(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_GAIN_SELECTION const gain_selection)
|
||||
{
|
||||
uint8_t setup_reg_value = 0;
|
||||
|
||||
ads1242_read_reg(dev, ADS1242_REG_SETUP, &setup_reg_value);
|
||||
setup_reg_value &= ~(ADS1242_REG_SETUP_BIT_PGA2 |
|
||||
ADS1242_REG_SETUP_BIT_PGA1 |
|
||||
ADS1242_REG_SETUP_BIT_PGA0);
|
||||
setup_reg_value |= (uint8_t)(gain_selection);
|
||||
ads1242_write_reg(dev, ADS1242_REG_SETUP, setup_reg_value);
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
ads1242_print_regs(dev, "ads1242_set_gain");
|
||||
#endif
|
||||
|
||||
/* It is necessary to perform a offset calibration after setting the gain */
|
||||
|
||||
ads1242_performSelfOffsetCalibration(dev);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_set_positive_input
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_set_positive_input(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_POSITIVE_INPUT_SELECTION const pos_in_sel)
|
||||
{
|
||||
uint8_t mux_reg_value = 0;
|
||||
|
||||
ads1242_read_reg(dev, ADS1242_REG_MUX, &mux_reg_value);
|
||||
mux_reg_value &= ~(ADS1242_REG_MUX_BIT_PSEL3 | ADS1242_REG_MUX_BIT_PSEL2 |
|
||||
ADS1242_REG_MUX_BIT_PSEL1 | ADS1242_REG_MUX_BIT_PSEL0);
|
||||
mux_reg_value |= (uint8_t)(pos_in_sel);
|
||||
ads1242_write_reg(dev, ADS1242_REG_MUX, mux_reg_value);
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
ads1242_print_regs(dev, "ads1242_set_positive_input");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_set_negative_input
|
||||
****************************************************************************/
|
||||
|
||||
static void ads1242_set_negative_input(FAR struct ads1242_dev_s *dev,
|
||||
ADS1242_NEGATIVE_INPUT_SELECTION const neg_in_sel)
|
||||
{
|
||||
uint8_t mux_reg_value = 0;
|
||||
|
||||
ads1242_read_reg(dev, ADS1242_REG_MUX, &mux_reg_value);
|
||||
mux_reg_value &= ~(ADS1242_REG_MUX_BIT_NSEL3 | ADS1242_REG_MUX_BIT_NSEL2 |
|
||||
ADS1242_REG_MUX_BIT_NSEL1 | ADS1242_REG_MUX_BIT_NSEL0);
|
||||
mux_reg_value |= (uint8_t)(neg_in_sel);
|
||||
ads1242_write_reg(dev, ADS1242_REG_MUX, mux_reg_value);
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
ads1242_print_regs(dev, "ads1242_set_negative_input");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_set_negative_input
|
||||
****************************************************************************/
|
||||
|
||||
static bool ads1242_is_data_ready(FAR struct ads1242_dev_s *dev)
|
||||
{
|
||||
uint8_t acr_reg_value = 0xFF;
|
||||
|
||||
ads1242_read_reg(dev, ADS1242_REG_ACR, &acr_reg_value);
|
||||
return (acr_reg_value & ADS1242_REG_ACR_BIT_nDRDY) == 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_print_regs
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
static void ads1242_print_regs(FAR struct ads1242_dev_s *dev, char const *msg)
|
||||
{
|
||||
uint8_t setup_reg_value = 0;
|
||||
uint8_t mux_reg_value = 0;
|
||||
uint8_t acr_reg_value = 0;
|
||||
|
||||
dbg("%s\n", msg);
|
||||
|
||||
ads1242_read_reg(dev, ADS1242_REG_SETUP, &setup_reg_value);
|
||||
ads1242_read_reg(dev, ADS1242_REG_MUX, &mux_reg_value);
|
||||
ads1242_read_reg(dev, ADS1242_REG_ACR, &acr_reg_value);
|
||||
|
||||
dbg("SETUP %02X\n", setup_reg_value);
|
||||
dbg("MUX %02X\n", mux_reg_value);
|
||||
dbg("ACR %02X\n", acr_reg_value);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG && CONFIG_DEBUG_VERBOSE */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_open
|
||||
****************************************************************************/
|
||||
|
||||
static int ads1242_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ads1242_dev_s *priv = inode->i_private;
|
||||
|
||||
ads1242_reset(priv);
|
||||
up_mdelay(100);
|
||||
|
||||
ads1242_performSelfGainCalibration(priv);
|
||||
up_mdelay(100);
|
||||
|
||||
/* SPEED = 1 -> fMod = fOsc / 256 (fMod = Modulator Clock Speed)
|
||||
* BUFEN = 1 -> Internal input buffer enabled -> results in a very high
|
||||
* impedance input for the ADC ~ 5 GOhm
|
||||
*/
|
||||
|
||||
ads1242_write_reg(priv, ADS1242_REG_ACR,
|
||||
ADS1242_REG_ACR_BIT_SPEED | ADS1242_REG_ACR_BIT_BUFEN);
|
||||
|
||||
ads1242_performSelfOffsetCalibration(priv);
|
||||
up_mdelay(100);
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
ads1242_print_regs(priv, "ads1242_open");
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
/****************************************************************************
|
||||
* Name: ads1242_close
|
||||
****************************************************************************/
|
||||
|
||||
static int ads1242_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ads1242_dev_s *priv = inode->i_private;
|
||||
|
||||
ads1242_reset(priv);
|
||||
up_mdelay(100);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ads1242_read(FAR struct file *filep,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ads1242_write(FAR struct file *filep,
|
||||
FAR const char *buffer, size_t buflen)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int ads1242_ioctl (FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct ads1242_dev_s *priv = inode->i_private;
|
||||
|
||||
int ret = OK;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* Read the result of an analog conversion */
|
||||
|
||||
case ANIOC_ADS2142_READ:
|
||||
{
|
||||
FAR uint32_t *data = (FAR uint32_t *)((uintptr_t)arg);
|
||||
ads1242_read_conversion_result(priv, data);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Set the gain of the ADC */
|
||||
|
||||
case ANIOC_ADS2142_SET_GAIN:
|
||||
{
|
||||
ads1242_set_gain(priv, (ADS1242_GAIN_SELECTION)(arg));
|
||||
}
|
||||
break;
|
||||
|
||||
/* Set the positive input of the ADC */
|
||||
|
||||
case ANIOC_ADS2142_SET_POSITIVE_INPUT:
|
||||
{
|
||||
ads1242_set_positive_input(priv,
|
||||
(ADS1242_POSITIVE_INPUT_SELECTION)(arg));
|
||||
}
|
||||
break;
|
||||
|
||||
/* Set the negative input of the ADC */
|
||||
|
||||
case ANIOC_ADS2142_SET_NEGATIVE_INPUT:
|
||||
{
|
||||
ads1242_set_negative_input(priv,
|
||||
(ADS1242_NEGATIVE_INPUT_SELECTION)(arg));
|
||||
}
|
||||
break;
|
||||
|
||||
/* Check if data is ready to be read */
|
||||
|
||||
case ANIOC_ADS2142_IS_DATA_READY:
|
||||
{
|
||||
FAR bool *is_data_ready = (FAR bool *)((uintptr_t)arg);
|
||||
*is_data_ready = ads1242_is_data_ready(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Perform a system offset calibration - Note: Zero input signal must
|
||||
* be applied.
|
||||
*/
|
||||
|
||||
case ANIOC_ADS2142_DO_SYSTEM_OFFSET_CALIB:
|
||||
{
|
||||
ads1242_performSystemOffsetCalibration(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Command was not recognized */
|
||||
|
||||
default:
|
||||
dbg ("Unrecognized cmd: %d\n", cmd);
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads1242_register
|
||||
*
|
||||
* Description:
|
||||
* Register the ADS1242 character device as 'devpath'
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the driver to register. E.g., "/dev/ads1242"
|
||||
* spi - An instance of the SPI interface to use to communicate with ADS1242
|
||||
* osc_freq_hz - The frequency of the ADS1242 oscillator in Hz. Required for
|
||||
* calculating the minimum delay periods when accessing the device via SPI.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ads1242_register(FAR const char *devpath, FAR struct spi_dev_s *spi,
|
||||
uint32_t const osc_freq_hz)
|
||||
{
|
||||
FAR struct ads1242_dev_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
DEBUGASSERT(spi != NULL);
|
||||
|
||||
/* Initialize the ADS1242 device structure */
|
||||
|
||||
priv = (FAR struct ads1242_dev_s *)kmm_malloc(sizeof(struct ads1242_dev_s));
|
||||
if (priv == NULL)
|
||||
{
|
||||
dbg ("Failed to allocate instance\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->spi = spi;
|
||||
|
||||
float const osc_period_us = (1000.0 * 1000.0) / ((float)(osc_freq_hz));
|
||||
priv->osc_period_us = (uint32_t)(osc_period_us);
|
||||
|
||||
/* Register the character driver */
|
||||
|
||||
ret = register_driver(devpath, &g_ads1242_fops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
dbg ("Failed to register driver: %d\n", ret);
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
/* setup SPI frequency */
|
||||
|
||||
SPI_SETFREQUENCY(spi, ADS1242_SPI_FREQUENCY);
|
||||
|
||||
/* Setup SPI mode */
|
||||
|
||||
SPI_SETMODE(spi, ADS1242_SPI_MODE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SPI && CONFIG_ADC_ADS1242 */
|
||||
|
|
@ -147,17 +147,17 @@ static struct up_dev_s g_adcpriv =
|
|||
{
|
||||
.mux = (const uint8_t [])
|
||||
{
|
||||
CONFIG_ADS1255_MUX,0
|
||||
CONFIG_ADS1255_MUX, 0
|
||||
},
|
||||
.sps = CONFIG_ADS1255_SPS,
|
||||
.sps = CONFIG_ADS1255_SPS,
|
||||
.channel = 0,
|
||||
.irq = CONFIG_ADS1255_IRQ,
|
||||
.irq = CONFIG_ADS1255_IRQ,
|
||||
};
|
||||
|
||||
static struct adc_dev_s g_adcdev =
|
||||
{
|
||||
.ad_ops = &g_adcops,
|
||||
.ad_priv= &g_adcpriv,
|
||||
.ad_ops = &g_adcops,
|
||||
.ad_priv = &g_adcpriv,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -166,12 +166,12 @@ static struct adc_dev_s g_adcdev =
|
|||
|
||||
static uint8_t getspsreg(uint16_t sps)
|
||||
{
|
||||
static const unsigned short sps_tab[]=
|
||||
static const unsigned short sps_tab[] =
|
||||
{
|
||||
3, 7, 12, 20, 27, 40, 55, 80,
|
||||
300, 750, 1500, 3000, 5000, 10000, 20000, 65535,
|
||||
};
|
||||
static const unsigned char sps_reg[]=
|
||||
static const unsigned char sps_reg[] =
|
||||
{
|
||||
0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x72,
|
||||
0x82, 0x92, 0xa1, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
|
||||
|
|
@ -203,12 +203,13 @@ static void adc_reset(FAR struct adc_dev_s *dev)
|
|||
|
||||
SPI_SETMODE(spi, SPIDEV_MODE1);
|
||||
SPI_SETBITS(spi, 8);
|
||||
(void)SPI_HWFEATURES(spi, 0);
|
||||
SPI_SETFREQUENCY(spi, CONFIG_ADS1255_FREQUENCY);
|
||||
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_SEND(spi, ADS125X_WREG + 0x03); /* WRITE SPS REG */
|
||||
SPI_SEND(spi, 0x00); /* count=1 */
|
||||
SPI_SEND(spi, 0x63);
|
||||
SPI_SELECT(spi, priv->devno, false);
|
||||
}
|
||||
|
||||
|
|
@ -227,22 +228,22 @@ static int adc_setup(FAR struct adc_dev_s *dev)
|
|||
if (ret == OK)
|
||||
{
|
||||
SPI_SELECT(spi, priv->devno, true);
|
||||
SPI_SEND(spi,ADS125X_WREG); /* WRITE REG from 0 */
|
||||
SPI_SEND(spi,0x03); /* count=4+1 */
|
||||
SPI_SEND(spi, ADS125X_WREG); /* WRITE REG from 0 */
|
||||
SPI_SEND(spi, 0x03); /* count=4+1 */
|
||||
if (priv->buf)
|
||||
{
|
||||
SPI_SEND(spi,ADS125X_BUFON); /* REG0 STATUS BUFFER ON */
|
||||
SPI_SEND(spi, ADS125X_BUFON); /* REG0 STATUS BUFFER ON */
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_SEND(spi,ADS125X_BUFOFF);
|
||||
SPI_SEND(spi, ADS125X_BUFOFF);
|
||||
}
|
||||
|
||||
SPI_SEND(spi,priv->mux[0]);
|
||||
SPI_SEND(spi,priv->pga); /* REG2 ADCON PGA=2 */
|
||||
SPI_SEND(spi,getspsreg(priv->sps));
|
||||
SPI_SEND(spi, priv->mux[0]);
|
||||
SPI_SEND(spi, priv->pga); /* REG2 ADCON PGA=2 */
|
||||
SPI_SEND(spi, getspsreg(priv->sps));
|
||||
usleep(1000);
|
||||
SPI_SEND(spi,ADS125X_SELFCAL);
|
||||
SPI_SEND(spi, ADS125X_SELFCAL);
|
||||
SPI_SELECT(spi, priv->devno, false);
|
||||
up_enable_irq(priv->irq);
|
||||
}
|
||||
|
|
@ -292,30 +293,30 @@ static int adc_interrupt(int irq, void *context)
|
|||
unsigned char ch;
|
||||
|
||||
SPI_SELECT(spi, priv->devno, true);
|
||||
SPI_SEND(spi,ADS125X_RDATA);
|
||||
SPI_SEND(spi, ADS125X_RDATA);
|
||||
up_udelay(10);
|
||||
buf[3]=SPI_SEND(spi,0xff);
|
||||
buf[2]=SPI_SEND(spi,0xff);
|
||||
buf[1]=SPI_SEND(spi,0xff);
|
||||
buf[0]=0;
|
||||
buf[3] = SPI_SEND(spi, 0xff);
|
||||
buf[2] = SPI_SEND(spi, 0xff);
|
||||
buf[1] = SPI_SEND(spi, 0xff);
|
||||
buf[0] = 0;
|
||||
|
||||
priv->channel++;
|
||||
ch = priv->mux[priv->channel];
|
||||
if ( ch == 0 )
|
||||
if (ch == 0)
|
||||
{
|
||||
priv->channel=0;
|
||||
priv->channel = 0;
|
||||
ch = priv->mux[0];
|
||||
}
|
||||
|
||||
SPI_SEND(spi,ADS125X_WREG+0x01);
|
||||
SPI_SEND(spi,0x00);
|
||||
SPI_SEND(spi,ch);
|
||||
SPI_SEND(spi,ADS125X_SYNC);
|
||||
SPI_SEND(spi, ADS125X_WREG + 0x01);
|
||||
SPI_SEND(spi, 0x00);
|
||||
SPI_SEND(spi, ch);
|
||||
SPI_SEND(spi, ADS125X_SYNC);
|
||||
up_udelay(2);
|
||||
SPI_SEND(spi,ADS125X_WAKEUP);
|
||||
SPI_SEND(spi, ADS125X_WAKEUP);
|
||||
SPI_SELECT(spi, priv->devno, false);
|
||||
|
||||
adc_receive(&g_adcdev,priv->channel,*(int32_t *)buf);
|
||||
adc_receive(&g_adcdev, priv->channel, *(int32_t *)buf);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <nuttx/analog/dac.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -74,9 +74,11 @@
|
|||
|
||||
static int dac_open(FAR struct file *filep);
|
||||
static int dac_close(FAR struct file *filep);
|
||||
static ssize_t dac_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||
static int dac_ioctl(FAR struct file *filep,int cmd,unsigned long arg);
|
||||
static ssize_t dac_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
static int dac_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
|
@ -141,7 +143,7 @@ static int dac_open(FAR struct file *filep)
|
|||
{
|
||||
/* Yes.. perform one time hardware initialization. */
|
||||
|
||||
irqstate_t flags = irqsave();
|
||||
irqstate_t flags = enter_critical_section();
|
||||
ret = dev->ad_ops->ao_setup(dev);
|
||||
if (ret == OK)
|
||||
{
|
||||
|
|
@ -155,7 +157,7 @@ static int dac_open(FAR struct file *filep)
|
|||
dev->ad_ocount = tmp;
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,9 +217,9 @@ static int dac_close(FAR struct file *filep)
|
|||
|
||||
/* Free the IRQ and disable the DAC device */
|
||||
|
||||
flags = irqsave(); /* Disable interrupts */
|
||||
flags = enter_critical_section(); /* Disable interrupts */
|
||||
dev->ad_ops->ao_shutdown(dev); /* Disable the DAC */
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
sem_post(&dev->ad_closesem);
|
||||
}
|
||||
|
|
@ -287,7 +289,7 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
|
||||
/* Interrupts must disabled throughout the following */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Check if the TX FIFO was empty when we started. That is a clue that we have
|
||||
* to kick off a new TX sequence.
|
||||
|
|
@ -299,7 +301,7 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
* shorter than the minimum.
|
||||
*/
|
||||
|
||||
if (buflen % 5 == 0 )
|
||||
if (buflen % 5 == 0)
|
||||
{
|
||||
msglen = 5;
|
||||
}
|
||||
|
|
@ -324,7 +326,7 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
msglen = 5;
|
||||
}
|
||||
|
||||
while ((buflen - nsent) >= msglen )
|
||||
while ((buflen - nsent) >= msglen)
|
||||
{
|
||||
/* Check if adding this new message would over-run the drivers ability to enqueue
|
||||
* xmit data.
|
||||
|
|
@ -394,27 +396,27 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
}
|
||||
else if (msglen == 4)
|
||||
{
|
||||
fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data=*(uint32_t *)&buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data&=0xffffff00;
|
||||
fifo->af_buffer[fifo->af_tail].am_channel = buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data = *(uint32_t *)&buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data &= 0xffffff00;
|
||||
}
|
||||
else if (msglen == 3)
|
||||
{
|
||||
fifo->af_buffer[fifo->af_tail].am_channel=buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent+1]);
|
||||
fifo->af_buffer[fifo->af_tail].am_data<<=16;
|
||||
fifo->af_buffer[fifo->af_tail].am_channel = buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data = (*(uint16_t *)&buffer[nsent+1]);
|
||||
fifo->af_buffer[fifo->af_tail].am_data <<= 16;
|
||||
}
|
||||
else if (msglen == 2)
|
||||
{
|
||||
fifo->af_buffer[fifo->af_tail].am_channel=0;
|
||||
fifo->af_buffer[fifo->af_tail].am_data=(*(uint16_t *)&buffer[nsent]);
|
||||
fifo->af_buffer[fifo->af_tail].am_data<<=16;
|
||||
fifo->af_buffer[fifo->af_tail].am_channel = 0;
|
||||
fifo->af_buffer[fifo->af_tail].am_data = (*(uint16_t *)&buffer[nsent]);
|
||||
fifo->af_buffer[fifo->af_tail].am_data <<= 16;
|
||||
}
|
||||
else if (msglen == 1)
|
||||
{
|
||||
fifo->af_buffer[fifo->af_tail].am_channel=0;
|
||||
fifo->af_buffer[fifo->af_tail].am_data=buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data<<=24;
|
||||
fifo->af_buffer[fifo->af_tail].am_channel = 0;
|
||||
fifo->af_buffer[fifo->af_tail].am_data = buffer[nsent];
|
||||
fifo->af_buffer[fifo->af_tail].am_data <<= 24;
|
||||
}
|
||||
|
||||
/* Increment the tail of the circular buffer */
|
||||
|
|
@ -426,21 +428,21 @@ static ssize_t dac_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
nsent += msglen;
|
||||
}
|
||||
|
||||
/* We get here after all messages have been added to the FIFO. Check if
|
||||
* we need to kick of the XMIT sequence.
|
||||
*/
|
||||
/* We get here after all messages have been added to the FIFO. Check if
|
||||
* we need to kick of the XMIT sequence.
|
||||
*/
|
||||
|
||||
if (empty)
|
||||
{
|
||||
dac_xmit(dev);
|
||||
}
|
||||
if (empty)
|
||||
{
|
||||
dac_xmit(dev);
|
||||
}
|
||||
|
||||
/* Return the number of bytes that were sent */
|
||||
|
||||
ret = nsent;
|
||||
|
||||
return_with_irqdisabled:
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,14 +121,6 @@
|
|||
# define spivdbg(x...)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -155,6 +147,7 @@ static void pga11x_configure(FAR struct spi_dev_s *spi)
|
|||
|
||||
SPI_SETMODE(spi, CONFIG_PGA11X_SPIMODE);
|
||||
SPI_SETBITS(spi, 8);
|
||||
(void)SPI_HWFEATURES(spi, 0);
|
||||
(void)SPI_SETFREQUENCY(spi, CONFIG_PGA11X_SPIFREQUENCY);
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +162,6 @@ static void pga11x_configure(FAR struct spi_dev_s *spi)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SPI_OWNBUS
|
||||
static void pga11x_lock(FAR struct spi_dev_s *spi)
|
||||
{
|
||||
spivdbg("Locking\n");
|
||||
|
|
@ -192,9 +184,6 @@ static void pga11x_lock(FAR struct spi_dev_s *spi)
|
|||
|
||||
pga11x_configure(spi);
|
||||
}
|
||||
#else
|
||||
# define pga11x_lock(spi)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pga11x_unlock
|
||||
|
|
@ -207,16 +196,12 @@ static void pga11x_lock(FAR struct spi_dev_s *spi)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SPI_OWNBUS
|
||||
static inline void pga11x_unlock(FAR struct spi_dev_s *spi)
|
||||
{
|
||||
spivdbg("Unlocking\n");
|
||||
|
||||
SPI_LOCK(spi, false);
|
||||
}
|
||||
#else
|
||||
# define pga11x_unlock(spi)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pga11x_send16
|
||||
|
|
@ -360,16 +345,8 @@ PGA11X_HANDLE pga11x_initialize(FAR struct spi_dev_s *spi)
|
|||
{
|
||||
spivdbg("Entry\n");
|
||||
|
||||
/* Configure the SPI us for the device. Do this now only if the PGA11X is
|
||||
* the only device on the bus.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SPI_OWNBUS
|
||||
pga11x_configure(spi);
|
||||
#endif
|
||||
|
||||
/* No other special state is required, just return the SPI driver instance
|
||||
* as the handle. This gives us a place to extend functionality in the
|
||||
/* No Special state is required, just return the SPI driver instance as
|
||||
* the handle. This gives us a place to extend functionality in the
|
||||
* future if neccessary.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ static int null_start(FAR struct audio_lowerhalf_s *dev);
|
|||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int null_stop(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
#else
|
||||
static int null_stop(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
|
|
@ -109,9 +109,9 @@ static int null_stop(FAR struct audio_lowerhalf_s *dev);
|
|||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int null_pause(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
static int null_resume(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
#else
|
||||
static int null_pause(FAR struct audio_lowerhalf_s *dev);
|
||||
static int null_resume(FAR struct audio_lowerhalf_s *dev);
|
||||
|
|
@ -432,7 +432,7 @@ static void *null_workerthread(pthread_addr_t pvarg)
|
|||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
while (!priv->terminate)
|
||||
#else
|
||||
for (;;)
|
||||
for (; ; )
|
||||
#endif
|
||||
{
|
||||
/* Wait for messages from our message queue */
|
||||
|
|
@ -573,7 +573,7 @@ static int null_start(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int null_stop(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int null_stop(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int null_stop(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
@ -611,7 +611,7 @@ static int null_stop(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int null_pause(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int null_pause(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int null_pause(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
@ -630,7 +630,7 @@ static int null_pause(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int null_resume(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int null_resume(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int null_resume(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -111,35 +111,35 @@ struct vs1053_struct_s
|
|||
|
||||
/* Our specific driver data goes here */
|
||||
|
||||
const FAR struct vs1053_lower_s *hw_lower;/* Pointer to the hardware lower functions */
|
||||
FAR struct spi_dev_s *spi; /* Pointer to the SPI bus */
|
||||
FAR struct ap_buffer_s *apb; /* Pointer to the buffer we are processing */
|
||||
struct dq_queue_s apbq; /* Our queue for enqueued buffers */
|
||||
unsigned long spi_freq; /* Frequency to run the SPI bus at. */
|
||||
unsigned long chip_freq; /* Current chip frequency */
|
||||
mqd_t mq; /* Message queue for receiving messages */
|
||||
char mqname[16]; /* Our message queue name */
|
||||
pthread_t threadid; /* ID of our thread */
|
||||
sem_t apbq_sem; /* Audio Pipeline Buffer Queue sem access */
|
||||
const FAR struct vs1053_lower_s *hw_lower; /* Pointer to the hardware lower functions */
|
||||
FAR struct spi_dev_s *spi; /* Pointer to the SPI bus */
|
||||
FAR struct ap_buffer_s *apb; /* Pointer to the buffer we are processing */
|
||||
struct dq_queue_s apbq; /* Our queue for enqueued buffers */
|
||||
unsigned long spi_freq; /* Frequency to run the SPI bus at. */
|
||||
unsigned long chip_freq; /* Current chip frequency */
|
||||
mqd_t mq; /* Message queue for receiving messages */
|
||||
char mqname[16]; /* Our message queue name */
|
||||
pthread_t threadid; /* ID of our thread */
|
||||
sem_t apbq_sem; /* Audio Pipeline Buffer Queue sem access */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
|
||||
int16_t volume; /* Current volume level */
|
||||
int16_t volume; /* Current volume level */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
|
||||
int16_t balance; /* Current balance level */
|
||||
int16_t balance; /* Current balance level */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_BALANCE */
|
||||
#endif /* CONFIG_AUDIO_EXCLUDE_VOLUME */
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_TONE
|
||||
uint8_t bass; /* Bass level */
|
||||
uint8_t treble; /* Bass level */
|
||||
uint8_t bass; /* Bass level */
|
||||
uint8_t treble; /* Bass level */
|
||||
#endif
|
||||
uint16_t endfillbytes;
|
||||
uint8_t endfillchar; /* Fill char to send when no more data */
|
||||
uint8_t endfillchar; /* Fill char to send when no more data */
|
||||
bool running;
|
||||
bool paused;
|
||||
bool endmode;
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
bool cancelmode;
|
||||
#endif
|
||||
bool busy; /* Set true when device reserved */
|
||||
bool busy; /* Set true when device reserved */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -167,7 +167,7 @@ static int vs1053_resume(FAR struct audio_lowerhalf_s *lower,
|
|||
static int vs1053_reserve(FAR struct audio_lowerhalf_s *lower,
|
||||
FAR void** ppContext);
|
||||
static int vs1053_release(FAR struct audio_lowerhalf_s *lower,
|
||||
FAR void* pContext);
|
||||
FAR void *pContext);
|
||||
#else
|
||||
static int vs1053_configure(FAR struct audio_lowerhalf_s *lower,
|
||||
FAR const struct audio_caps_s *pCaps);
|
||||
|
|
@ -219,7 +219,10 @@ static const struct audio_ops_s g_audioops =
|
|||
|
||||
/* ISR context pointers */
|
||||
|
||||
static struct vs1053_struct_s* g_isrdata[CONFIG_VS1053_DEVICE_COUNT] = { NULL, };
|
||||
static struct vs1053_struct_s *g_isrdata[CONFIG_VS1053_DEVICE_COUNT] =
|
||||
{
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Volume control log table. This table is in increments of 2% of
|
||||
* requested volume level and is the register value that should be
|
||||
|
|
@ -271,6 +274,7 @@ static void vs1053_spi_lock(FAR struct spi_dev_s *dev, unsigned long freq_mhz)
|
|||
|
||||
SPI_SETMODE(dev, CONFIG_VS1053_SPIMODE);
|
||||
SPI_SETBITS(dev, 8);
|
||||
(void)SPI_HWFEATURES(dev, 0);
|
||||
(void)SPI_SETFREQUENCY(dev, freq_mhz);
|
||||
}
|
||||
|
||||
|
|
@ -1518,14 +1522,14 @@ static int vs1053_start(FAR struct audio_lowerhalf_s *lower)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int vs1053_stop(FAR struct audio_lowerhalf_s *lower, FAR void* session)
|
||||
static int vs1053_stop(FAR struct audio_lowerhalf_s *lower, FAR void *session)
|
||||
#else
|
||||
static int vs1053_stop(FAR struct audio_lowerhalf_s *lower)
|
||||
#endif
|
||||
{
|
||||
FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower;
|
||||
struct audio_msg_s term_msg;
|
||||
FAR void* value;
|
||||
struct audio_msg_s term_msg;
|
||||
FAR void *value;
|
||||
|
||||
/* Send a message to stop all audio streaming */
|
||||
|
||||
|
|
@ -1562,7 +1566,7 @@ static int vs1053_stop(FAR struct audio_lowerhalf_s *lower)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int vs1053_pause(FAR struct audio_lowerhalf_s *lower, FAR void* session)
|
||||
static int vs1053_pause(FAR struct audio_lowerhalf_s *lower, FAR void *session)
|
||||
#else
|
||||
static int vs1053_pause(FAR struct audio_lowerhalf_s *lower)
|
||||
#endif
|
||||
|
|
@ -1591,7 +1595,7 @@ static int vs1053_pause(FAR struct audio_lowerhalf_s *lower)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int vs1053_resume(FAR struct audio_lowerhalf_s *lower, FAR void* session)
|
||||
static int vs1053_resume(FAR struct audio_lowerhalf_s *lower, FAR void *session)
|
||||
#else
|
||||
static int vs1053_resume(FAR struct audio_lowerhalf_s *lower)
|
||||
#endif
|
||||
|
|
@ -1620,9 +1624,9 @@ static int vs1053_resume(FAR struct audio_lowerhalf_s *lower)
|
|||
****************************************************************************/
|
||||
|
||||
static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower,
|
||||
FAR struct ap_buffer_s *apb )
|
||||
FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower;
|
||||
FAR struct vs1053_struct_s *dev = (struct vs1053_struct_s *)lower;
|
||||
struct audio_msg_s term_msg;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1661,7 +1665,7 @@ static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower,
|
|||
****************************************************************************/
|
||||
|
||||
static int vs1053_cancelbuffer(FAR struct audio_lowerhalf_s *lower,
|
||||
FAR struct ap_buffer_s *apb )
|
||||
FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -1871,7 +1875,7 @@ struct audio_lowerhalf_s *vs1053_initialize(FAR struct spi_dev_s *spi,
|
|||
* for the DREQ to be active indicating the device is ready
|
||||
*/
|
||||
|
||||
retry = 200;;
|
||||
retry = 200;
|
||||
while (!lower->read_dreq(lower) && retry)
|
||||
{
|
||||
up_udelay(10);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Audio device driver for Wolfson Microelectronics WM8904 Audio codec.
|
||||
*
|
||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References:
|
||||
|
|
@ -59,10 +59,11 @@
|
|||
#include <queue.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <nuttx/i2c.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/audio/i2s.h>
|
||||
|
|
@ -72,14 +73,6 @@
|
|||
|
||||
#include "wm8904.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
|
@ -133,7 +126,7 @@ static int wm8904_start(FAR struct audio_lowerhalf_s *dev);
|
|||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int wm8904_stop(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
#else
|
||||
static int wm8904_stop(FAR struct audio_lowerhalf_s *dev);
|
||||
#endif
|
||||
|
|
@ -141,9 +134,9 @@ static int wm8904_stop(FAR struct audio_lowerhalf_s *dev);
|
|||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int wm8904_pause(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
static int wm8904_resume(FAR struct audio_lowerhalf_s *dev,
|
||||
FAR void* session);
|
||||
FAR void *session);
|
||||
#else
|
||||
static int wm8904_pause(FAR struct audio_lowerhalf_s *dev);
|
||||
static int wm8904_resume(FAR struct audio_lowerhalf_s *dev);
|
||||
|
|
@ -232,7 +225,10 @@ const uint8_t g_sysclk_scaleb1[WM8904_BCLK_MAXDIV+1] =
|
|||
#ifndef CONFIG_WM8904_CLKDEBUG
|
||||
static
|
||||
#endif
|
||||
const uint8_t g_fllratio[WM8904_NFLLRATIO] = {1, 2, 4, 8, 16};
|
||||
const uint8_t g_fllratio[WM8904_NFLLRATIO] =
|
||||
{
|
||||
1, 2, 4, 8, 16
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
|
@ -263,17 +259,19 @@ uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
|||
|
||||
/* Set up to write the address */
|
||||
|
||||
msg[0].addr = priv->lower->address;
|
||||
msg[0].flags = 0;
|
||||
msg[0].buffer = ®addr;
|
||||
msg[0].length = 1;
|
||||
msg[0].frequency = priv->lower->frequency;
|
||||
msg[0].addr = priv->lower->address;
|
||||
msg[0].flags = 0;
|
||||
msg[0].buffer = ®addr;
|
||||
msg[0].length = 1;
|
||||
|
||||
/* Followed by the read data */
|
||||
|
||||
msg[1].addr = priv->lower->address;
|
||||
msg[1].flags = I2C_M_READ;
|
||||
msg[1].buffer = data;
|
||||
msg[1].length = 2;
|
||||
msg[1].frequency = priv->lower->frequency;
|
||||
msg[1].addr = priv->lower->address;
|
||||
msg[1].flags = I2C_M_READ;
|
||||
msg[1].buffer = data;
|
||||
msg[1].length = 2;
|
||||
|
||||
/* Read the register data. The returned value is the number messages
|
||||
* completed.
|
||||
|
|
@ -287,10 +285,10 @@ uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
|||
|
||||
auddbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
|
||||
|
||||
ret = up_i2creset(priv->i2c);
|
||||
ret = I2C_RESET(priv->i2c);
|
||||
if (ret < 0)
|
||||
{
|
||||
auddbg("ERROR: up_i2creset failed: %d\n", ret);
|
||||
auddbg("ERROR: I2C_RESET failed: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
|
|
@ -329,8 +327,15 @@ uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
|
|||
static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
|
||||
uint16_t regval)
|
||||
{
|
||||
struct i2c_config_s config;
|
||||
int retries;
|
||||
|
||||
/* Setup up the I2C configuration */
|
||||
|
||||
config.frequency = priv->lower->frequency;
|
||||
config.address = priv->lower->address;
|
||||
config.addrlen = 7;
|
||||
|
||||
/* Try up to three times to read the register */
|
||||
|
||||
for (retries = 1; retries <= 3; retries++)
|
||||
|
|
@ -348,18 +353,18 @@ static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
|
|||
* completed.
|
||||
*/
|
||||
|
||||
ret = I2C_WRITE(priv->i2c, data, 3);
|
||||
ret = i2c_write(priv->i2c, &config, data, 3);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
/* Perhaps the I2C bus is locked up? Try to shake the bus free */
|
||||
|
||||
auddbg("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
|
||||
auddbg("WARNING: i2c_write failed: %d ... Resetting\n", ret);
|
||||
|
||||
ret = up_i2creset(priv->i2c);
|
||||
ret = I2C_RESET(priv->i2c);
|
||||
if (ret < 0)
|
||||
{
|
||||
auddbg("ERROR: up_i2creset failed: %d\n", ret);
|
||||
auddbg("ERROR: I2C_RESET failed: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
|
|
@ -726,7 +731,7 @@ static void wm8904_setbitrate(FAR struct wm8904_dev_s *priv)
|
|||
minfout = WM8904_FVCO_MAX / WM8904_MAXOUTDIV;
|
||||
divndx = 0;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
/* Calculate the new value of Fout that we would need to provide
|
||||
* with this SYSCLK divider in place.
|
||||
|
|
@ -1312,7 +1317,7 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s,
|
|||
* against that possibility.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Add the completed buffer to the end of our doneq. We do not yet
|
||||
* decrement the reference count.
|
||||
|
|
@ -1329,7 +1334,7 @@ static void wm8904_senddone(FAR struct i2s_dev_s *i2s,
|
|||
/* REVISIT: This can be overwritten */
|
||||
|
||||
priv->result = result;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Now send a message to the worker thread, informing it that there are
|
||||
* buffers in the done queue that need to be cleaned up.
|
||||
|
|
@ -1364,13 +1369,13 @@ static void wm8904_returnbuffers(FAR struct wm8904_dev_s *priv)
|
|||
* use interrupt controls to protect against that possibility.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
while (dq_peek(&priv->doneq) != NULL)
|
||||
{
|
||||
/* Take the next buffer from the queue of completed transfers */
|
||||
|
||||
apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->doneq);
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
audvdbg("Returning: apb=%p curbyte=%d nbytes=%d flags=%04x\n",
|
||||
apb, apb->curbyte, apb->nbytes, apb->flags);
|
||||
|
|
@ -1405,10 +1410,10 @@ static void wm8904_returnbuffers(FAR struct wm8904_dev_s *priv)
|
|||
#else
|
||||
priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK);
|
||||
#endif
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -1456,9 +1461,9 @@ static int wm8904_sendbuffer(FAR struct wm8904_dev_s *priv)
|
|||
* to avoid a possible race condition.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
priv->inflight++;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Send the entire audio buffer via I2S. What is a reasonable timeout
|
||||
* to use? This would depend on the bit rate and size of the buffer.
|
||||
|
|
@ -1585,7 +1590,7 @@ static int wm8904_start(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int wm8904_stop(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int wm8904_stop(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int wm8904_stop(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
@ -1622,7 +1627,7 @@ static int wm8904_stop(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int wm8904_pause(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int wm8904_pause(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int wm8904_pause(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
@ -1651,7 +1656,7 @@ static int wm8904_pause(FAR struct audio_lowerhalf_s *dev)
|
|||
|
||||
#ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
static int wm8904_resume(FAR struct audio_lowerhalf_s *dev, FAR void* session)
|
||||
static int wm8904_resume(FAR struct audio_lowerhalf_s *dev, FAR void *session)
|
||||
#else
|
||||
static int wm8904_resume(FAR struct audio_lowerhalf_s *dev)
|
||||
#endif
|
||||
|
|
@ -2461,7 +2466,7 @@ static void wm8904_hw_reset(FAR struct wm8904_dev_s *priv)
|
|||
****************************************************************************/
|
||||
|
||||
FAR struct audio_lowerhalf_s *
|
||||
wm8904_initialize(FAR struct i2c_dev_s *i2c, FAR struct i2s_dev_s *i2s,
|
||||
wm8904_initialize(FAR struct i2c_master_s *i2c, FAR struct i2s_dev_s *i2s,
|
||||
FAR const struct wm8904_lower_s *lower)
|
||||
{
|
||||
FAR struct wm8904_dev_s *priv;
|
||||
|
|
@ -2489,12 +2494,6 @@ FAR struct audio_lowerhalf_s *
|
|||
dq_init(&priv->pendq);
|
||||
dq_init(&priv->doneq);
|
||||
|
||||
/* Initialize I2C */
|
||||
|
||||
auddbg("address=%02x frequency=%d\n", lower->address, lower->frequency);
|
||||
I2C_SETFREQUENCY(i2c, lower->frequency);
|
||||
I2C_SETADDRESS(i2c, lower->address, 7);
|
||||
|
||||
/* Software reset. This puts all WM8904 registers back in their
|
||||
* default state.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1067,7 +1067,7 @@ struct wm8904_dev_s
|
|||
/* Our specific driver data goes here */
|
||||
|
||||
const FAR struct wm8904_lower_s *lower; /* Pointer to the board lower functions */
|
||||
FAR struct i2c_dev_s *i2c; /* I2C driver to use */
|
||||
FAR struct i2c_master_s *i2c; /* I2C driver to use */
|
||||
FAR struct i2s_dev_s *i2s; /* I2S driver to use */
|
||||
struct dq_queue_s pendq; /* Queue of pending buffers to be sent */
|
||||
struct dq_queue_s doneq; /* Queue of sent buffers to be returned */
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ void wm8904_clock_analysis(FAR struct audio_lowerhalf_s *dev,
|
|||
else
|
||||
{
|
||||
syslog(LOG_INFO, " MCLK_DIV: 2\n");
|
||||
sysclk >>=1;
|
||||
sysclk >>= 1;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, " SYSCLK: %lu (after divider)\n", (unsigned long)sysclk);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/bch/bch_internal.h
|
||||
* drivers/bch/bch.h
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2014-2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -33,8 +33,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __FS_BCH_INTERNAL_H
|
||||
#define __FS_BCH_INTERNAL_H
|
||||
#ifndef __DRIVERS_BCH_BCH_H
|
||||
#define __DRIVERS_BCH_BCH_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
|
@ -61,23 +61,24 @@
|
|||
|
||||
struct bchlib_s
|
||||
{
|
||||
struct inode *inode; /* I-node of the block driver */
|
||||
sem_t sem; /* For atomic accesses to this structure */
|
||||
size_t nsectors; /* Number of sectors supported by the device */
|
||||
size_t sector; /* The current sector in the buffer */
|
||||
uint16_t sectsize; /* The size of one sector on the device */
|
||||
uint8_t refs; /* Number of references */
|
||||
bool dirty; /* Data has been written to the buffer */
|
||||
bool readonly; /* true: Only read operations are supported */
|
||||
FAR uint8_t *buffer; /* One sector buffer */
|
||||
FAR struct inode *inode; /* I-node of the block driver */
|
||||
uint32_t sectsize; /* The size of one sector on the device */
|
||||
size_t nsectors; /* Number of sectors supported by the device */
|
||||
size_t sector; /* The current sector in the buffer */
|
||||
sem_t sem; /* For atomic accesses to this structure */
|
||||
uint8_t refs; /* Number of references */
|
||||
bool dirty; /* true: Data has been written to the buffer */
|
||||
bool readonly; /* true: Only read operations are supported */
|
||||
bool unlinked; /* true: The driver has been unlinked */
|
||||
FAR uint8_t *buffer; /* One sector buffer */
|
||||
|
||||
#if defined(CONFIG_BCH_ENCRYPTION)
|
||||
uint8_t key[CONFIG_BCH_ENCRYPTION_KEY_SIZE]; /* Encryption key */
|
||||
uint8_t key[CONFIG_BCH_ENCRYPTION_KEY_SIZE]; /* Encryption key */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Global Variables
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
|
|
@ -103,4 +104,4 @@ EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FS_BCH_INTERNAL_H */
|
||||
#endif /* __DRIVERS_BCH_BCH_H */
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/bch/bchdev_driver.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2014-2015 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -77,6 +77,9 @@ static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer,
|
|||
size_t buflen);
|
||||
static int bch_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int bch_unlink(FAR struct inode *inode);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
|
|
@ -84,14 +87,17 @@ static int bch_ioctl(FAR struct file *filep, int cmd,
|
|||
|
||||
const struct file_operations bch_fops =
|
||||
{
|
||||
bch_open, /* open */
|
||||
bch_close, /* close */
|
||||
bch_read, /* read */
|
||||
bch_write, /* write */
|
||||
bch_seek, /* seek */
|
||||
bch_ioctl /* ioctl */
|
||||
bch_open, /* open */
|
||||
bch_close, /* close */
|
||||
bch_read, /* read */
|
||||
bch_write, /* write */
|
||||
bch_seek, /* seek */
|
||||
bch_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, 0 /* poll */
|
||||
, 0 /* poll */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
, bch_unlink /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -152,7 +158,8 @@ static int bch_close(FAR struct file *filep)
|
|||
(void)bchlib_flushsector(bch);
|
||||
|
||||
/* Decrement the reference count (I don't use bchlib_decref() because I
|
||||
* want the entire close operation to be atomic wrt other driver operations.
|
||||
* want the entire close operation to be atomic wrt other driver
|
||||
* operations.
|
||||
*/
|
||||
|
||||
if (bch->refs == 0)
|
||||
|
|
@ -162,6 +169,30 @@ static int bch_close(FAR struct file *filep)
|
|||
else
|
||||
{
|
||||
bch->refs--;
|
||||
|
||||
/* If the reference count decremented to zero AND if the character
|
||||
* driver has been unlinked, then teardown the BCH device now.
|
||||
*/
|
||||
|
||||
if (bch->refs == 0 && bch->unlinked)
|
||||
{
|
||||
/* Tear the driver down now. */
|
||||
|
||||
ret = bchlib_teardown((FAR void *)bch);
|
||||
|
||||
/* bchlib_teardown() would only fail if there are outstanding
|
||||
* references on the device. Since we know that is not true, it
|
||||
* should not fail at all.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(ret >= 0);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Return without releasing the stale semaphore */
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bchlib_semgive(bch);
|
||||
|
|
@ -302,6 +333,8 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
|
||||
/* Is this a request to get the private data structure */
|
||||
|
||||
if (cmd == DIOC_GETPRIV)
|
||||
{
|
||||
FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)((uintptr_t)arg);
|
||||
|
|
@ -319,17 +352,87 @@ static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
|
||||
bchlib_semgive(bch);
|
||||
}
|
||||
#if defined(CONFIG_BCH_ENCRYPTION)
|
||||
|
||||
#ifdef CONFIG_BCH_ENCRYPTION
|
||||
/* Is this a request to set the encryption key? */
|
||||
|
||||
else if (cmd == DIOC_SETKEY)
|
||||
{
|
||||
memcpy(bch->key, (void*)arg, CONFIG_BCH_ENCRYPTION_KEY_SIZE);
|
||||
memcpy(bch->key, (FAR void *)arg, CONFIG_BCH_ENCRYPTION_KEY_SIZE);
|
||||
ret = OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Otherwise, pass the IOCTL command on to the contained block driver */
|
||||
|
||||
else
|
||||
{
|
||||
FAR struct inode *bchinode = bch->inode;
|
||||
|
||||
/* Does the block driver support the ioctl method? */
|
||||
|
||||
if (bchinode->u.i_bops->ioctl != NULL)
|
||||
{
|
||||
ret = bchinode->u.i_bops->ioctl(bchinode, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: bch_unlink
|
||||
*
|
||||
* Handle unlinking of the BCH device
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int bch_unlink(FAR struct inode *inode)
|
||||
{
|
||||
FAR struct bchlib_s *bch;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
bch = (FAR struct bchlib_s *)inode->i_private;
|
||||
|
||||
/* Get exclusive access to the BCH device */
|
||||
|
||||
bchlib_semtake(bch);
|
||||
|
||||
/* Indicate that the driver has been unlinked */
|
||||
|
||||
bch->unlinked = true;
|
||||
|
||||
/* If there are no open references to the drvier then teardown the BCH
|
||||
* device now.
|
||||
*/
|
||||
|
||||
if (bch->refs == 0)
|
||||
{
|
||||
/* Tear the driver down now. */
|
||||
|
||||
ret = bchlib_teardown((FAR void *)bch);
|
||||
|
||||
/* bchlib_teardown() would only fail if there are outstanding
|
||||
* references on the device. Since we know that is not true, it
|
||||
* should not fail at all.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(ret >= 0);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Return without releasing the stale semaphore */
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
bchlib_semgive(bch);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
#if defined(CONFIG_BCH_ENCRYPTION)
|
||||
# include <crypto/crypto.h>
|
||||
|
|
@ -91,13 +91,16 @@ static void bch_xor(uint32_t *R, uint32_t *A, uint32_t *B)
|
|||
static int bch_cypher(FAR struct bchlib_s *bch, int encrypt)
|
||||
{
|
||||
int blocks = bch->sectsize / 16;
|
||||
uint32_t *buffer = (uint32_t*)bch->buffer;
|
||||
FAR uint32_t *buffer = (FAR uint32_t *)bch->buffer;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < blocks; i++, buffer += 16 / sizeof(uint32_t) )
|
||||
{
|
||||
uint32_t T[4];
|
||||
uint32_t X[4] = {bch->sector, 0, 0, i};
|
||||
uint32_t X[4] =
|
||||
{
|
||||
bch->sector, 0, 0, i
|
||||
};
|
||||
|
||||
aes_cypher(X, X, 16, NULL, bch->key, CONFIG_BCH_ENCRYPTION_KEY_SIZE,
|
||||
AES_MODE_ECB, CYPHER_ENCRYPT);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -132,7 +132,6 @@ ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t le
|
|||
|
||||
/* Adjust pointers and counts */
|
||||
|
||||
sectoffset = 0;
|
||||
sector++;
|
||||
|
||||
if (sector >= bch->nsectors)
|
||||
|
|
@ -149,7 +148,7 @@ ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t le
|
|||
* into the user buffer.
|
||||
*/
|
||||
|
||||
if (len >= bch->sectsize )
|
||||
if (len >= bch->sectsize)
|
||||
{
|
||||
nsectors = len / bch->sectsize;
|
||||
if (sector + nsectors > bch->nsectors)
|
||||
|
|
@ -167,9 +166,7 @@ ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t le
|
|||
|
||||
/* Adjust pointers and counts */
|
||||
|
||||
sectoffset = 0;
|
||||
sector += nsectors;
|
||||
|
||||
nbytes = nsectors * bch->sectsize;
|
||||
bytesread += nbytes;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -93,7 +93,7 @@ int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle)
|
|||
|
||||
/* Allocate the BCH state structure */
|
||||
|
||||
bch = (FAR struct bchlib_s*)kmm_zalloc(sizeof(struct bchlib_s));
|
||||
bch = (FAR struct bchlib_s *)kmm_zalloc(sizeof(struct bchlib_s));
|
||||
if (!bch)
|
||||
{
|
||||
fdbg("Failed to allocate BCH structure\n");
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#include <nuttx/fs/fs.h>
|
||||
|
||||
#include "bch_internal.h"
|
||||
#include "bch.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -132,7 +132,6 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, si
|
|||
|
||||
/* Adjust pointers and counts */
|
||||
|
||||
sectoffset = 0;
|
||||
sector++;
|
||||
|
||||
if (sector >= bch->nsectors)
|
||||
|
|
@ -149,7 +148,7 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, si
|
|||
* directly from the user buffer.
|
||||
*/
|
||||
|
||||
if (len >= bch->sectsize )
|
||||
if (len >= bch->sectsize)
|
||||
{
|
||||
nsectors = len / bch->sectsize;
|
||||
if (sector + nsectors > bch->nsectors)
|
||||
|
|
@ -169,9 +168,7 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, si
|
|||
|
||||
/* Adjust pointers and counts */
|
||||
|
||||
sectoffset = 0;
|
||||
sector += nsectors;
|
||||
|
||||
nbytes = nsectors * bch->sectsize;
|
||||
byteswritten += nbytes;
|
||||
|
||||
|
|
|
|||
336
drivers/can.c
336
drivers/can.c
|
|
@ -54,13 +54,48 @@
|
|||
#include <nuttx/arch.h>
|
||||
#include <nuttx/can.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#ifdef CONFIG_CAN_TXREADY
|
||||
# include <nuttx/wqueue.h>
|
||||
#endif
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#ifdef CONFIG_CAN
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifdef CONFIG_CAN_TXREADY
|
||||
# if !defined(CONFIG_SCHED_WORKQUEUE)
|
||||
# error Work queue support required in this configuration
|
||||
# undef CONFIG_CAN_TXREADY
|
||||
# undef CONFIG_CAN_TXREADY_LOPRI
|
||||
# undef CONFIG_CAN_TXREADY_HIPRI
|
||||
# elif defined(CONFIG_CAN_TXREADY_LOPRI)
|
||||
# undef CONFIG_CAN_TXREADY_HIPRI
|
||||
# ifdef CONFIG_SCHED_LPWORK
|
||||
# define CANWORK LPWORK
|
||||
# else
|
||||
# error Low priority work queue support required in this configuration
|
||||
# undef CONFIG_CAN_TXREADY
|
||||
# undef CONFIG_CAN_TXREADY_LOPRI
|
||||
# endif
|
||||
# elif defined(CONFIG_CAN_TXREADY_HIPRI)
|
||||
# ifdef CONFIG_SCHED_HPWORK
|
||||
# define CANWORK HPWORK
|
||||
# else
|
||||
# error High priority work queue support required in this configuration
|
||||
# undef CONFIG_CAN_TXREADY
|
||||
# undef CONFIG_CAN_TXREADY_HIPRI
|
||||
# endif
|
||||
# else
|
||||
# error No work queue selection
|
||||
# undef CONFIG_CAN_TXREADY
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
/* Non-standard debug that may be enabled just for testing CAN */
|
||||
|
||||
|
|
@ -95,6 +130,9 @@ static uint8_t can_dlc2bytes(uint8_t dlc);
|
|||
#if 0 /* Not used */
|
||||
static uint8_t can_bytes2dlc(uint8_t nbytes);
|
||||
#endif
|
||||
#ifdef CONFIG_CAN_TXREADY
|
||||
static void can_txready_work(FAR void *arg);
|
||||
#endif
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
|
|
@ -246,6 +284,59 @@ static uint8_t can_bytes2dlc(FAR struct sam_can_s *priv, uint8_t nbytes)
|
|||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: can_txready_work
|
||||
*
|
||||
* Description:
|
||||
* This function performs deferred processing from can_txready. See the
|
||||
* discription of can_txready below for additionla information.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CAN_TXREADY
|
||||
static void can_txready_work(FAR void *arg)
|
||||
{
|
||||
FAR struct can_dev_s *dev = (FAR struct can_dev_s *)arg;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
canllvdbg("xmit head: %d queue: %d tail: %d\n",
|
||||
dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue,
|
||||
dev->cd_xmit.tx_tail);
|
||||
|
||||
/* Verify that the xmit FIFO is not empty. The following operations must
|
||||
* be performed with interrupt disabled.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
|
||||
{
|
||||
/* Send the next message in the FIFO. */
|
||||
|
||||
ret = can_xmit(dev);
|
||||
|
||||
/* If the message was successfully queued in the H/W FIFO, then
|
||||
* can_txdone() should have been called. If the S/W FIFO were
|
||||
* full before then there should now be free space in the S/W FIFO.
|
||||
*/
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Are there any threads waiting for space in the TX FIFO? */
|
||||
|
||||
if (dev->cd_ntxwaiters > 0)
|
||||
{
|
||||
/* Yes.. Inform them that new xmit space is available */
|
||||
|
||||
(void)sem_post(&dev->cd_xmit.tx_sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: can_open
|
||||
*
|
||||
|
|
@ -291,7 +382,7 @@ static int can_open(FAR struct file *filep)
|
|||
{
|
||||
/* Yes.. perform one time hardware initialization. */
|
||||
|
||||
irqstate_t flags = irqsave();
|
||||
irqstate_t flags = enter_critical_section();
|
||||
ret = dev_setup(dev);
|
||||
if (ret == OK)
|
||||
{
|
||||
|
|
@ -312,7 +403,7 @@ static int can_open(FAR struct file *filep)
|
|||
dev->cd_ocount = 1;
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -395,9 +486,9 @@ static int can_close(FAR struct file *filep)
|
|||
|
||||
/* Free the IRQ and disable the CAN device */
|
||||
|
||||
flags = irqsave(); /* Disable interrupts */
|
||||
flags = enter_critical_section(); /* Disable interrupts */
|
||||
dev_shutdown(dev); /* Disable the CAN */
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
sem_post(&dev->cd_closesem);
|
||||
}
|
||||
|
|
@ -434,7 +525,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
|||
{
|
||||
/* Interrupts must be disabled while accessing the cd_recv FIFO */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
while (dev->cd_recv.rx_head == dev->cd_recv.rx_tail)
|
||||
{
|
||||
/* The receive FIFO is empty -- was non-blocking mode selected? */
|
||||
|
|
@ -501,7 +592,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer,
|
|||
ret = nread;
|
||||
|
||||
return_with_irqdisabled:
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -531,7 +622,15 @@ static int can_xmit(FAR struct can_dev_s *dev)
|
|||
if (dev->cd_xmit.tx_head == dev->cd_xmit.tx_tail)
|
||||
{
|
||||
DEBUGASSERT(dev->cd_xmit.tx_queue == dev->cd_xmit.tx_head);
|
||||
|
||||
#ifndef CONFIG_CAN_TXREADY
|
||||
/* We can disable CAN TX interrupts -- unless there is a H/W FIFO. In
|
||||
* that case, TX interrupts must stay enabled until the H/W FIFO is
|
||||
* fully emptied.
|
||||
*/
|
||||
|
||||
dev_txint(dev, false);
|
||||
#endif
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
@ -554,7 +653,7 @@ static int can_xmit(FAR struct can_dev_s *dev)
|
|||
DEBUGASSERT(dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail);
|
||||
|
||||
/* Increment the FIFO queue index before sending (because dev_send()
|
||||
* might call can_txdone().
|
||||
* might call can_txdone()).
|
||||
*/
|
||||
|
||||
tmpndx = dev->cd_xmit.tx_queue;
|
||||
|
|
@ -602,7 +701,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
|
|||
|
||||
/* Interrupts must disabled throughout the following */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Check if the TX is inactive when we started. In certain race conditions,
|
||||
* there may be a pending interrupt to kick things back off, but we will
|
||||
|
|
@ -634,7 +733,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
|
|||
{
|
||||
/* The transmit FIFO is full -- was non-blocking mode selected? */
|
||||
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
if ((filep->f_oflags & O_NONBLOCK) != 0)
|
||||
{
|
||||
if (nsent == 0)
|
||||
{
|
||||
|
|
@ -655,7 +754,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
|
|||
|
||||
if (inactive)
|
||||
{
|
||||
can_xmit(dev);
|
||||
(void)can_xmit(dev);
|
||||
}
|
||||
|
||||
/* Wait for a message to be sent */
|
||||
|
|
@ -698,21 +797,21 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer,
|
|||
nsent += msglen;
|
||||
}
|
||||
|
||||
/* We get here after all messages have been added to the FIFO. Check if
|
||||
* we need to kick of the XMIT sequence.
|
||||
*/
|
||||
/* We get here after all messages have been added to the FIFO. Check if
|
||||
* we need to kick of the XMIT sequence.
|
||||
*/
|
||||
|
||||
if (inactive)
|
||||
{
|
||||
can_xmit(dev);
|
||||
}
|
||||
if (inactive)
|
||||
{
|
||||
(void)can_xmit(dev);
|
||||
}
|
||||
|
||||
/* Return the number of bytes that were sent */
|
||||
|
||||
ret = nsent;
|
||||
|
||||
return_with_irqdisabled:
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -737,7 +836,7 @@ static inline ssize_t can_rtrread(FAR struct can_dev_s *dev,
|
|||
|
||||
/* Disable interrupts through this operation */
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Find an available slot in the pending RTR list */
|
||||
|
||||
|
|
@ -767,7 +866,7 @@ static inline ssize_t can_rtrread(FAR struct can_dev_s *dev,
|
|||
}
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -795,7 +894,7 @@ static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
*/
|
||||
|
||||
case CANIOC_RTR:
|
||||
ret = can_rtrread(dev, (struct canioc_rtr_s*)((uintptr_t)arg));
|
||||
ret = can_rtrread(dev, (FAR struct canioc_rtr_s *)((uintptr_t)arg));
|
||||
break;
|
||||
|
||||
/* Not a "built-in" ioctl command.. perhaps it is unique to this
|
||||
|
|
@ -859,11 +958,14 @@ int can_register(FAR const char *path, FAR struct can_dev_s *dev)
|
|||
* Description:
|
||||
* Called from the CAN interrupt handler when new read data is available
|
||||
*
|
||||
* Parameters:
|
||||
* Input Parameters:
|
||||
* dev - CAN driver state structure
|
||||
* hdr - CAN message header
|
||||
* data - CAN message data (if DLC > 0)
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* CAN interrupts are disabled.
|
||||
*
|
||||
|
|
@ -983,17 +1085,72 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr,
|
|||
* Name: can_txdone
|
||||
*
|
||||
* Description:
|
||||
* Called from the CAN interrupt handler at the completion of a send
|
||||
* operation.
|
||||
* Called when the hardware has processed the outgoing TX message. This
|
||||
* normally means that the CAN messages was sent out on the wire. But
|
||||
* if the CAN hardware supports a H/W TX FIFO, then this call may mean
|
||||
* only that the CAN message has been added to the H/W FIFO. In either
|
||||
* case, the upper-half CAN driver can remove the outgoing message from
|
||||
* the S/W FIFO and discard it.
|
||||
*
|
||||
* Parameters:
|
||||
* This function may be called in different contexts, depending upon the
|
||||
* nature of the underlying CAN hardware.
|
||||
*
|
||||
* 1. No H/W TX FIFO (CONFIG_CAN_TXREADY not defined)
|
||||
*
|
||||
* This function is only called from the CAN interrupt handler at the
|
||||
* completion of a send operation.
|
||||
*
|
||||
* can_write() -> can_xmit() -> dev_send()
|
||||
* CAN interrupt -> can_txdone()
|
||||
*
|
||||
* If the CAN hardware is busy, then the call to dev_send() will
|
||||
* fail, the S/W TX FIFO will accumulate outgoing messages, and the
|
||||
* thread calling can_write() may eventually block waiting for space in
|
||||
* the S/W TX FIFO.
|
||||
*
|
||||
* When the CAN hardware completes the transfer and processes the
|
||||
* CAN interrupt, the call to can_txdone() will make space in the S/W
|
||||
* TX FIFO and will awaken the waiting can_write() thread.
|
||||
*
|
||||
* 2a. H/W TX FIFO (CONFIG_CAN_TXREADY=y) and S/W TX FIFO not full
|
||||
*
|
||||
* This function will be called back from dev_send() immediately when a
|
||||
* new CAN message is added to H/W TX FIFO:
|
||||
*
|
||||
* can_write() -> can_xmit() -> dev_send() -> can_txdone()
|
||||
*
|
||||
* When the H/W TX FIFO becomes full, dev_send() will fail and
|
||||
* can_txdone() will not be called. In this case the S/W TX FIFO will
|
||||
* accumulate outgoing messages, and the thread calling can_write() may
|
||||
* eventually block waiting for space in the S/W TX FIFO.
|
||||
*
|
||||
* 2b. H/W TX FIFO (CONFIG_CAN_TXREADY=y) and S/W TX FIFO full
|
||||
*
|
||||
* In this case, the thread calling can_write() is blocked waiting for
|
||||
* space in the S/W TX FIFO. can_txdone() will be called, indirectly,
|
||||
* from can_txready_work() running on the thread of the work queue.
|
||||
*
|
||||
* CAN interrupt -> can_txready() -> Schedule can_txready_work()
|
||||
* can_txready_work() -> can_xmit() -> dev_send() -> can_txdone()
|
||||
*
|
||||
* The call dev_send() should not fail in this case and the subsequent
|
||||
* call to can_txdone() will make space in the S/W TX FIFO and will
|
||||
* awaken the waiting thread.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The specific CAN device
|
||||
* hdr - The 16-bit CAN header
|
||||
* data - An array contain the CAN data.
|
||||
*
|
||||
* Return:
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are disabled. This is required by can_xmit() which is called
|
||||
* by this function. Interrupts are explicitly disabled when called
|
||||
* through can_write(). Interrupts are expected be disabled when called
|
||||
* from the CAN interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int can_txdone(FAR struct can_dev_s *dev)
|
||||
|
|
@ -1007,6 +1164,12 @@ int can_txdone(FAR struct can_dev_s *dev)
|
|||
|
||||
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
|
||||
{
|
||||
/* The tx_queue index is incremented each time can_xmit() queues
|
||||
* the transmission. When can_txdone() is called, the tx_queue
|
||||
* index should always have been advanced beyond the current tx_head
|
||||
* index.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(dev->cd_xmit.tx_head != dev->cd_xmit.tx_queue);
|
||||
|
||||
/* Remove the message at the head of the xmit FIFO */
|
||||
|
|
@ -1037,4 +1200,123 @@ int can_txdone(FAR struct can_dev_s *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: can_txready
|
||||
*
|
||||
* Description:
|
||||
* Called from the CAN interrupt handler at the completion of a send
|
||||
* operation. This interface is needed only for CAN hardware that
|
||||
* supports queing of outgoing messages in a H/W FIFO.
|
||||
*
|
||||
* The CAN upper half driver also supports a queue of output messages in a
|
||||
* S/W FIFO. Messages are added to that queue when when can_write() is
|
||||
* called and removed from the queue in can_txdone() when each TX message
|
||||
* is complete.
|
||||
*
|
||||
* After each message is added to the S/W FIFO, the CAN upper half driver
|
||||
* will attempt to send the message by calling into the lower half driver.
|
||||
* That send will not be performed if the lower half driver is busy, i.e.,
|
||||
* if dev_txready() returns false. In that case, the number of messages in
|
||||
* the S/W FIFO can grow. If the S/W FIFO becomes full, then can_write()
|
||||
* will wait for space in the S/W FIFO.
|
||||
*
|
||||
* If the CAN hardware does not support a H/W FIFO then busy means that
|
||||
* the hardware is actively sending the message and is guaranteed to
|
||||
* become non-busy (i.e, dev_txready()) when the send transfer completes
|
||||
* and can_txdone() is called. So the call to can_txdone() means that the
|
||||
* transfer has completed and also that the hardware is ready to accept
|
||||
* another transfer.
|
||||
*
|
||||
* If the CAN hardware supports a H/W FIFO, can_txdone() is not called
|
||||
* when the tranfer is complete, but rather when the transfer is queued in
|
||||
* the H/W FIFO. When the H/W FIFO becomes full, then dev_txready() will
|
||||
* report false and the number of queued messages in the S/W FIFO will grow.
|
||||
*
|
||||
* There is no mechanism in this case to inform the upper half driver when
|
||||
* the hardware is again available, when there is again space in the H/W
|
||||
* FIFO. can_txdone() will not be called again. If the S/W FIFO becomes
|
||||
* full, then the upper half driver will wait for space to become
|
||||
* available, but there is no event to awaken it and the driver will hang.
|
||||
*
|
||||
* Enabling this feature adds support for the can_txready() interface.
|
||||
* This function is called from the lower half driver's CAN interrupt
|
||||
* handler each time a TX transfer completes. This is a sure indication
|
||||
* that the H/W FIFO is no longer full. can_txready() will then awaken
|
||||
* the can_write() logic and the hang condition is avoided.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The specific CAN device
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
* Interrupts are disabled. This function may execute in the context of
|
||||
* and interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CAN_TXREADY
|
||||
int can_txready(FAR struct can_dev_s *dev)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
|
||||
canllvdbg("xmit head: %d queue: %d tail: %d waiters: %d\n",
|
||||
dev->cd_xmit.tx_head, dev->cd_xmit.tx_queue, dev->cd_xmit.tx_tail,
|
||||
dev->cd_ntxwaiters);
|
||||
|
||||
/* Verify that the xmit FIFO is not empty. This is safe because interrupts
|
||||
* are always disabled when calling into can_xmit(); this cannot collide
|
||||
* with ongoing activity from can_write().
|
||||
*/
|
||||
|
||||
if (dev->cd_xmit.tx_head != dev->cd_xmit.tx_tail)
|
||||
{
|
||||
/* Is work already scheduled? */
|
||||
|
||||
if (work_available(&dev->cd_work))
|
||||
{
|
||||
/* Yes... schedule to perform can_txready() work on the worker
|
||||
* thread. Although data structures are protected by disabling
|
||||
* interrupts, the can_xmit() operations may involve semaphore
|
||||
* operations and, hence, should not be done at the interrupt
|
||||
* level.
|
||||
*/
|
||||
|
||||
ret = work_queue(CANWORK, &dev->cd_work, can_txready_work, dev, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EBUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There should not be any threads waiting for space in the S/W TX
|
||||
* FIFO is it is empty.
|
||||
*
|
||||
* REVISIT: Assertion can fire in certain race conditions, i.e, when
|
||||
* all waiters have been awakened but have not yet had a chance to
|
||||
* decrement cd_ntxwaiters.
|
||||
*/
|
||||
|
||||
//DEBUGASSERT(dev->cd_ntxwaiters == 0);
|
||||
|
||||
#if 0 /* REVISIT */
|
||||
/* When the H/W FIFO has been emptied, we can disable further TX
|
||||
* interrupts.
|
||||
*
|
||||
* REVISIT: The fact that the S/W FIFO is empty does not mean that
|
||||
* the H/W FIFO is also empty. If we really want this to work this
|
||||
* way, then we would probably need and additional parameter to tell
|
||||
* us if the H/W FIFO is empty.
|
||||
*/
|
||||
|
||||
dev_txint(dev, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_CAN_TXREADY */
|
||||
#endif /* CONFIG_CAN */
|
||||
|
|
|
|||
|
|
@ -50,11 +50,13 @@
|
|||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t devnull_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t devnull_write(FAR struct file *, FAR const char *, size_t);
|
||||
static ssize_t devnull_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t devnull_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
bool setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -106,7 +108,7 @@ static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
{
|
||||
if (setup)
|
||||
{
|
||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||
fds->revents |= (fds->events & (POLLIN | POLLOUT));
|
||||
if (fds->revents != 0)
|
||||
{
|
||||
sem_post(fds->sem);
|
||||
|
|
|
|||
|
|
@ -50,11 +50,13 @@
|
|||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t devzero_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t devzero_write(FAR struct file *, FAR const char *, size_t);
|
||||
static ssize_t devzero_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t devzero_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
bool setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -109,7 +111,7 @@ static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
|||
{
|
||||
if (setup)
|
||||
{
|
||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||
fds->revents |= (fds->events & (POLLIN | POLLOUT));
|
||||
if (fds->revents != 0)
|
||||
{
|
||||
sem_post(fds->sem);
|
||||
|
|
|
|||
|
|
@ -173,10 +173,10 @@
|
|||
|
||||
struct ee25xx_geom_s
|
||||
{
|
||||
uint8_t bytes : 4; /*power of two of 128 bytes (0:128 1:256 2:512 etc) */
|
||||
uint8_t pagesize : 4; /*power of two of 8 bytes (0:8 1:16 2:32 3:64 etc)*/
|
||||
uint8_t addrlen : 4; /*number of bytes in command address field */
|
||||
uint8_t flags : 4; /*special address management for 25xx040, 1=A8 in inst*/
|
||||
uint8_t bytes : 4; /* Power of two of 128 bytes (0:128 1:256 2:512 etc) */
|
||||
uint8_t pagesize : 4; /* Power of two of 8 bytes (0:8 1:16 2:32 3:64 etc) */
|
||||
uint8_t addrlen : 4; /* Number of bytes in command address field */
|
||||
uint8_t flags : 4; /* Special address management for 25xx040, 1=A8 in inst */
|
||||
};
|
||||
|
||||
/* Private data attached to the inode */
|
||||
|
|
@ -219,29 +219,29 @@ static const struct ee25xx_geom_s g_ee25xx_devices[] =
|
|||
{
|
||||
/* Microchip devices */
|
||||
|
||||
{ 0, 1, 1, 0}, /* 25xx010A 128 16 1*/
|
||||
{ 1, 1, 1, 0}, /* 25xx020A 256 16 1*/
|
||||
{ 2, 1, 1, 1}, /* 25xx040 512 16 1+bit*/
|
||||
{ 3, 1, 1, 0}, /* 25xx080 1024 16 1*/
|
||||
{ 3, 2, 2, 0}, /* 25xx080B 1024 32 2*/
|
||||
{ 4, 1, 2, 0}, /* 25xx160 2048 16 2*/
|
||||
{ 4, 2, 2, 0}, /* 25xx160B/D 2048 32 2*/
|
||||
{ 5, 2, 2, 0}, /* 25xx320 4096 32 2*/
|
||||
{ 6, 2, 2, 0}, /* 25xx640 8192 32 2*/
|
||||
{ 7, 3, 2, 0}, /* 25xx128 16384 64 2*/
|
||||
{ 8, 3, 2, 0}, /* 25xx256 32768 64 2*/
|
||||
{ 9, 4, 2, 0}, /* 25xx512 65536 128 2*/
|
||||
{10, 5, 3, 0}, /* 25xx1024 131072 256 3*/
|
||||
{ 0, 1, 1, 0}, /* 25xx010A 128 16 1 */
|
||||
{ 1, 1, 1, 0}, /* 25xx020A 256 16 1 */
|
||||
{ 2, 1, 1, 1}, /* 25xx040 512 16 1+bit */
|
||||
{ 3, 1, 1, 0}, /* 25xx080 1024 16 1 */
|
||||
{ 3, 2, 2, 0}, /* 25xx080B 1024 32 2 */
|
||||
{ 4, 1, 2, 0}, /* 25xx160 2048 16 2 */
|
||||
{ 4, 2, 2, 0}, /* 25xx160B/D 2048 32 2 */
|
||||
{ 5, 2, 2, 0}, /* 25xx320 4096 32 2 */
|
||||
{ 6, 2, 2, 0}, /* 25xx640 8192 32 2 */
|
||||
{ 7, 3, 2, 0}, /* 25xx128 16384 64 2 */
|
||||
{ 8, 3, 2, 0}, /* 25xx256 32768 64 2 */
|
||||
{ 9, 4, 2, 0}, /* 25xx512 65536 128 2 */
|
||||
{10, 5, 3, 0}, /* 25xx1024 131072 256 3 */
|
||||
|
||||
/* Atmel devices */
|
||||
|
||||
{ 0, 0, 1, 0}, /* AT25010B 128 8 1*/
|
||||
{ 1, 0, 1, 0}, /* AT25020B 256 8 1*/
|
||||
{ 2, 0, 1, 1}, /* AT25040B 512 8 1+bit*/
|
||||
{ 0, 0, 1, 0}, /* AT25010B 128 8 1 */
|
||||
{ 1, 0, 1, 0}, /* AT25020B 256 8 1 */
|
||||
{ 2, 0, 1, 1}, /* AT25040B 512 8 1+bit */
|
||||
|
||||
/* STM devices */
|
||||
|
||||
{11, 5, 3, 0}, /* M95M02 262144 256 3*/
|
||||
{11, 5, 3, 0}, /* M95M02 262144 256 3 */
|
||||
};
|
||||
|
||||
/* Driver operations */
|
||||
|
|
@ -288,6 +288,7 @@ static void ee25xx_lock(FAR struct spi_dev_s *dev)
|
|||
|
||||
SPI_SETMODE(dev, CONFIG_EE25XX_SPIMODE);
|
||||
SPI_SETBITS(dev, 8);
|
||||
(void)SPI_HWFEATURES(dev, 0);
|
||||
(void)SPI_SETFREQUENCY(dev, 10000000); /* This is the default speed */
|
||||
}
|
||||
|
||||
|
|
@ -337,7 +338,7 @@ static void ee25xx_sendcmd(FAR struct spi_dev_s *spi, uint8_t cmd,
|
|||
|
||||
buf[cmdlen++] = addr & 0xff;
|
||||
|
||||
SPI_SNDBLOCK(spi,buf,cmdlen);
|
||||
SPI_SNDBLOCK(spi, buf, cmdlen);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -488,7 +489,7 @@ static int ee25xx_open(FAR struct file *filep)
|
|||
|
||||
/* Increment the reference count */
|
||||
|
||||
if ( (eedev->refs + 1) == 0)
|
||||
if ((eedev->refs + 1) == 0)
|
||||
{
|
||||
ret = -EMFILE;
|
||||
}
|
||||
|
|
@ -678,7 +679,7 @@ static ssize_t ee25xx_write(FAR struct file *filep, FAR const char *buffer,
|
|||
|
||||
/* Clamp len to avoid crossing the end of the memory */
|
||||
|
||||
if ( (len + filep->f_pos) > eedev->size)
|
||||
if ((len + filep->f_pos) > eedev->size)
|
||||
{
|
||||
len = eedev->size - filep->f_pos;
|
||||
}
|
||||
|
|
@ -807,7 +808,7 @@ int ee25xx_initialize(FAR struct spi_dev_s *dev, FAR char *devname,
|
|||
eedev->size = 128 << g_ee25xx_devices[devtype].bytes;
|
||||
eedev->pgsize = 8 << g_ee25xx_devices[devtype].pagesize;
|
||||
eedev->addrlen = g_ee25xx_devices[devtype].addrlen << 3;
|
||||
if ( (g_ee25xx_devices[devtype].flags & 1))
|
||||
if ((g_ee25xx_devices[devtype].flags & 1))
|
||||
{
|
||||
eedev->addrlen = 9;
|
||||
}
|
||||
|
|
|
|||
34
drivers/i2c/Kconfig
Normal file
34
drivers/i2c/Kconfig
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
if I2C
|
||||
|
||||
config I2C_SLAVE
|
||||
bool "I2C Slave"
|
||||
default n
|
||||
|
||||
config I2C_POLLED
|
||||
bool "Polled I2C (no interrupts)"
|
||||
default n
|
||||
|
||||
config I2C_RESET
|
||||
bool "Support I2C reset interface method"
|
||||
default n
|
||||
depends on ARCH_HAVE_I2CRESET
|
||||
|
||||
config I2C_TRACE
|
||||
bool "Enable I2C trace debug"
|
||||
default n
|
||||
|
||||
config I2C_NTRACE
|
||||
int "Number of I2C trace records"
|
||||
default 32
|
||||
depends on I2C_TRACE
|
||||
|
||||
config I2C_DRIVER
|
||||
bool "I2C character driver"
|
||||
default n
|
||||
|
||||
endif # I2C
|
||||
52
drivers/i2c/Make.defs
Normal file
52
drivers/i2c/Make.defs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
############################################################################
|
||||
# drivers/i2c/Make.defs
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Don't build anything if there is no I2C support
|
||||
|
||||
ifeq ($(CONFIG_I2C),y)
|
||||
|
||||
CSRCS += i2c_read.c i2c_write.c i2c_writeread.c
|
||||
|
||||
ifeq ($(CONFIG_I2C_DRIVER),y)
|
||||
CSRCS += i2c_driver.c
|
||||
endif
|
||||
|
||||
# Include I2C device driver build support
|
||||
|
||||
DEPPATH += --dep-path i2c
|
||||
VPATH += :i2c
|
||||
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)i2c}
|
||||
endif
|
||||
|
||||
438
drivers/i2c/i2c_driver.c
Normal file
438
drivers/i2c/i2c_driver.c
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
/****************************************************************************
|
||||
* drivers/i2c/i2c_driver.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#ifdef CONFIG_I2C_DRIVER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Device naming ************************************************************/
|
||||
|
||||
#define DEVNAME_FMT "/dev/i2c%d"
|
||||
#define DEVNAME_FMTLEN (8 + 3 + 1)
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
/* CONFIG_DEBUG_I2C + CONFIG_DEBUG enables general I2C debug output. */
|
||||
|
||||
#ifdef CONFIG_DEBUG_I2C
|
||||
# define i2cdbg dbg
|
||||
# define i2cvdbg vdbg
|
||||
#else
|
||||
# define i2cdbg(x...)
|
||||
# define i2cvdbg(x...)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Driver state structure */
|
||||
|
||||
struct i2c_driver_s
|
||||
{
|
||||
FAR struct i2c_master_s *i2c; /* Contained I2C lower half driver */
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
sem_t exclsem; /* Mutual exclusion */
|
||||
int16_t crefs; /* Number of open references */
|
||||
bool unlinked; /* True, driver has been unlinked */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int i2cdrvr_open(FAR struct file *filep);
|
||||
static int i2cdrvr_close(FAR struct file *filep);
|
||||
static ssize_t i2cdrvr_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t i2cdrvr_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t buflen);
|
||||
static int i2cdrvr_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int i2cdrvr_unlink(FAR struct inode *inode);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations i2cdrvr_fops =
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
i2cdrvr_open, /* open */
|
||||
i2cdrvr_close, /* close */
|
||||
#else
|
||||
0, /* open */
|
||||
0, /* close */
|
||||
#endif
|
||||
i2cdrvr_read, /* read */
|
||||
i2cdrvr_write, /* write */
|
||||
0, /* seek */
|
||||
i2cdrvr_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, 0 /* poll */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
, i2cdrvr_unlink /* unlink */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_open
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int i2cdrvr_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct i2c_driver_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Get our private data structure */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
|
||||
priv = (FAR struct i2c_driver_s *)inode->i_private;
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Get exclusive access to the I2C driver state structure */
|
||||
|
||||
ret = sem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode < 0);
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
/* Increment the count of open references on the RTC driver */
|
||||
|
||||
priv->crefs++;
|
||||
DEBUGASSERT(priv->crefs > 0);
|
||||
|
||||
sem_post(&priv->exclsem);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_close
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int i2cdrvr_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct i2c_driver_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Get our private data structure */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
|
||||
priv = (FAR struct i2c_driver_s *)inode->i_private;
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Get exclusive access to the I2C driver state structure */
|
||||
|
||||
ret = sem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode < 0);
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
/* Decrement the count of open references on the RTC driver */
|
||||
|
||||
DEBUGASSERT(priv->crefs > 0);
|
||||
priv->crefs--;
|
||||
|
||||
/* If the count has decremented to zero and the driver has been unlinked,
|
||||
* then commit Hara-Kiri now.
|
||||
*/
|
||||
|
||||
if (priv->crefs <= 0 && priv->unlinked)
|
||||
{
|
||||
sem_destroy(&priv->exclsem);
|
||||
kmm_free(priv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
sem_post(&priv->exclsem);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t i2cdrvr_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
return 0; /* Return EOF */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t i2cdrvr_write(FAR struct file *filep, FAR const char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
return len; /* Say that everything was written */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int i2cdrvr_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct i2c_driver_s *priv;
|
||||
FAR struct i2c_transfer_s *transfer;
|
||||
int ret;
|
||||
|
||||
i2cvdbg("cmd=%d arg=%lu\n", cmd, arg);
|
||||
|
||||
/* Get our private data structure */
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
|
||||
priv = (FAR struct i2c_driver_s *)inode->i_private;
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Get exclusive access to the I2C driver state structure */
|
||||
|
||||
ret = sem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode < 0);
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
/* Process the IOCTL command */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* Command: I2CIOC_TRANSFER
|
||||
* Description: Perform an I2C transfer
|
||||
* Argument: A reference to an instance of struct i2c_transfer_s.
|
||||
* Dependencies: CONFIG_I2C_DRIVER
|
||||
*/
|
||||
|
||||
case I2CIOC_TRANSFER:
|
||||
{
|
||||
/* Get the reference to the i2c_transfer_s structure */
|
||||
|
||||
transfer = (FAR struct i2c_transfer_s *)((uintptr_t)arg);
|
||||
DEBUGASSERT(transfer != NULL);
|
||||
|
||||
/* Perform the transfer */
|
||||
|
||||
ret = I2C_TRANSFER(priv->i2c, transfer->msgv, transfer->msgc);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
/* Command: I2CIOC_RESET
|
||||
* Description: Perform an I2C bus reset in an attempt to break loose
|
||||
* stuck I2C devices.
|
||||
* Argument: None
|
||||
* Dependencies: CONFIG_I2C_DRIVER && CONFIG_I2C_RESET
|
||||
*/
|
||||
|
||||
case I2CIOC_RESET:
|
||||
{
|
||||
ret = I2C_RESET(priv->i2c);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
sem_post(&priv->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2cdrvr_unlink
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int i2cdrvr_unlink(FAR struct inode *inode)
|
||||
{
|
||||
FAR struct i2c_driver_s *priv;
|
||||
int ret;
|
||||
|
||||
/* Get our private data structure */
|
||||
|
||||
DEBUGASSERT(inode != NULL && inode->i_private != NULL);
|
||||
priv = (FAR struct i2c_driver_s *)inode->i_private;
|
||||
|
||||
/* Get exclusive access to the I2C driver state structure */
|
||||
|
||||
ret = sem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode < 0);
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
/* Are there open references to the driver data structure? */
|
||||
|
||||
if (priv->crefs <= 0)
|
||||
{
|
||||
sem_destroy(&priv->exclsem);
|
||||
kmm_free(priv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* No... just mark the driver as unlinked and free the resouces when the
|
||||
* last client closes their reference to the driver.
|
||||
*/
|
||||
|
||||
priv->unlinked = true;
|
||||
sem_post(&priv->exclsem);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2c_register
|
||||
*
|
||||
* Description:
|
||||
* Create and register the I2C character driver.
|
||||
*
|
||||
* The I2C character driver is a simple character driver that supports I2C
|
||||
* transfers. The intent of this driver is to support I2C testing. It is
|
||||
* not suitable for use in any real driver application.
|
||||
*
|
||||
* Input Parameters:
|
||||
* i2c - An instance of the lower half I2C driver
|
||||
* bus - The I2C bus number. This will be used as the I2C device minor
|
||||
* number. The I2C character device will be registered as /dev/i2cN
|
||||
* where N is the minor number
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i2c_register(FAR struct i2c_master_s *i2c, int bus)
|
||||
{
|
||||
FAR struct i2c_driver_s *priv;
|
||||
char devname[DEVNAME_FMTLEN];
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
DEBUGASSERT(i2c != NULL && (unsigned)bus < 1000);
|
||||
|
||||
/* Allocate a I2C character device structure */
|
||||
|
||||
priv = (FAR struct i2c_driver_s *)kmm_zalloc(sizeof(struct i2c_driver_s));
|
||||
if (priv)
|
||||
{
|
||||
/* Initialize the I2C character device structure */
|
||||
|
||||
priv->i2c = i2c;
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
sem_init(&priv->exclsem, 0, 1);
|
||||
#endif
|
||||
|
||||
/* Create the character device name */
|
||||
|
||||
snprintf(devname, DEVNAME_FMTLEN, DEVNAME_FMT, bus);
|
||||
ret = register_driver(devname, &i2cdrvr_fops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Free the device structure if we failed to create the character
|
||||
* device.
|
||||
*/
|
||||
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
/* Return the result of the registration */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_I2C_DRIVER */
|
||||
90
drivers/i2c/i2c_read.c
Normal file
90
drivers/i2c/i2c_read.c
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/****************************************************************************
|
||||
* drivers/i2c/i2c_read.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2c_read
|
||||
*
|
||||
* Description:
|
||||
* Receive a block of data from I2C. Each read operation will be an
|
||||
* 'atomic' operation in the sense that any other I2C actions will be
|
||||
* serialized and pend until this read completes.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* buffer - A pointer to a buffer of data to receive the data from the device
|
||||
* buflen - The requested number of bytes to be read
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: success, <0: A negated errno
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i2c_read(FAR struct i2c_master_s *dev,
|
||||
FAR const struct i2c_config_s *config,
|
||||
FAR uint8_t *buffer, int buflen)
|
||||
{
|
||||
struct i2c_msg_s msg;
|
||||
unsigned int flags;
|
||||
|
||||
/* 7- or 10-bit? */
|
||||
|
||||
flags = (config->addrlen == 10) ? I2C_M_TEN : 0;
|
||||
|
||||
/* Setup for the transfer */
|
||||
|
||||
msg.frequency = config->frequency,
|
||||
msg.addr = config->address,
|
||||
msg.flags = (flags | I2C_M_READ);
|
||||
msg.buffer = buffer;
|
||||
msg.length = buflen;
|
||||
|
||||
/* Then perform the transfer. */
|
||||
|
||||
return I2C_TRANSFER(dev, &msg, 1);
|
||||
}
|
||||
86
drivers/i2c/i2c_write.c
Normal file
86
drivers/i2c/i2c_write.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/****************************************************************************
|
||||
* drivers/i2c/i2c_write.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2c_write
|
||||
*
|
||||
* Description:
|
||||
* Send a block of data on I2C. Each write operation will be an 'atomic'
|
||||
* operation in the sense that any other I2C actions will be serialized
|
||||
* and pend until this write completes.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* config - Described the I2C configuration
|
||||
* buffer - A pointer to the read-only buffer of data to be written to device
|
||||
* buflen - The number of bytes to send from the buffer
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: success, <0: A negated errno
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i2c_write(FAR struct i2c_master_s *dev,
|
||||
FAR const struct i2c_config_s *config,
|
||||
FAR const uint8_t *buffer, int buflen)
|
||||
{
|
||||
struct i2c_msg_s msg;
|
||||
|
||||
/* Setup for the transfer */
|
||||
|
||||
msg.frequency = config->frequency,
|
||||
msg.addr = config->address;
|
||||
msg.flags = (config->addrlen == 10) ? I2C_M_TEN : 0;
|
||||
msg.buffer = (FAR uint8_t *)buffer; /* Override const */
|
||||
msg.length = buflen;
|
||||
|
||||
/* Then perform the transfer. */
|
||||
|
||||
return I2C_TRANSFER(dev, &msg, 1);
|
||||
}
|
||||
114
drivers/i2c/i2c_writeread.c
Normal file
114
drivers/i2c/i2c_writeread.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/****************************************************************************
|
||||
* drivers/i2c/i2c_writeread.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: i2c_writeread
|
||||
*
|
||||
* Description:
|
||||
* Send a block of data on I2C followed by restarted read access. This
|
||||
* provides a convenient wrapper to the transfer function.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* config - Described the I2C configuration
|
||||
* wbuffer - A pointer to the read-only buffer of data to be written to device
|
||||
* wbuflen - The number of bytes to send from the buffer
|
||||
* rbuffer - A pointer to a buffer of data to receive the data from the device
|
||||
* rbuflen - The requested number of bytes to be read
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: success, <0: A negated errno
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int i2c_writeread(FAR struct i2c_master_s *dev,
|
||||
FAR const struct i2c_config_s *config,
|
||||
FAR const uint8_t *wbuffer, int wbuflen,
|
||||
FAR uint8_t *rbuffer, int rbuflen)
|
||||
{
|
||||
struct i2c_msg_s msg[2];
|
||||
unsigned int flags;
|
||||
|
||||
/* 7- or 10-bit address? */
|
||||
|
||||
DEBUGASSERT(config->addrlen == 10 || config->addrlen == 7);
|
||||
flags = (config->addrlen == 10) ? I2C_M_TEN : 0;
|
||||
|
||||
/* Format two messages: The first is a write */
|
||||
|
||||
msg[0].frequency = config->frequency,
|
||||
msg[0].addr = config->address;
|
||||
msg[0].flags = flags;
|
||||
msg[0].buffer = (FAR uint8_t *)wbuffer; /* Override const */
|
||||
msg[0].length = wbuflen;
|
||||
|
||||
/* The second is either a read (rbuflen > 0) or a write (rbuflen < 0) with
|
||||
* no restart.
|
||||
*/
|
||||
|
||||
if (rbuflen > 0)
|
||||
{
|
||||
msg[1].flags = (flags | I2C_M_READ);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg[1].flags = (flags | I2C_M_NORESTART);
|
||||
rbuflen = -rbuflen;
|
||||
}
|
||||
|
||||
msg[1].frequency = config->frequency,
|
||||
msg[1].addr = config->address;
|
||||
msg[1].buffer = rbuffer;
|
||||
msg[1].length = rbuflen;
|
||||
|
||||
/* Then perform the transfer. */
|
||||
|
||||
return I2C_TRANSFER(dev, msg, 2);
|
||||
}
|
||||
|
||||
|
|
@ -322,6 +322,49 @@ config STMPE811_REGDEBUG
|
|||
|
||||
endif # INPUT_STMPE811
|
||||
|
||||
config BUTTONS
|
||||
bool "Button Inputs"
|
||||
default n
|
||||
---help---
|
||||
Enable standard button upper half driver.
|
||||
|
||||
if BUTTONS
|
||||
|
||||
config BUTTONS_LOWER
|
||||
bool "Generic Lower Half Button Dirver"
|
||||
default n
|
||||
depends on ARCH_BUTTONS && ARCH_IRQBUTTONS
|
||||
---help---
|
||||
If the board supports the standard button interfaces as
|
||||
defined in include/nuttx/board.h header file, then this
|
||||
standard button lower half driver might be usable.
|
||||
|
||||
In order for this generic driver to be usable:
|
||||
|
||||
1. The board implementation must provide the button
|
||||
interfaces as defined in include/nuttx/board.h
|
||||
2. The board implementation must support interrupts for each
|
||||
button.
|
||||
3. The board.h header file must provide the definition
|
||||
NUM_BUTTONS, and
|
||||
4. The board.h header file must not include any other
|
||||
header files that are not accessibble in this context
|
||||
(such as those in arch/<arch>/src/<chip>) UNLESS those
|
||||
inclusions are conditioned on __KERNEL__. button_lower.c
|
||||
will undefine __KERNEL__ before included board.h.
|
||||
|
||||
If your board does not meet these requirements, then the
|
||||
button_lower.c file can still be copied to your your
|
||||
board src/ directory and modified for your specific board
|
||||
requirements.
|
||||
|
||||
config BUTTONS_NPOLLWAITERS
|
||||
int "Max Number of Poll Waiters"
|
||||
default 2
|
||||
depends on !DISABLE_POLL
|
||||
|
||||
endif # BUTTONS
|
||||
|
||||
config DJOYSTICK
|
||||
bool "Discrete Joystick"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
############################################################################
|
||||
# drivers/input/Make.defs
|
||||
#
|
||||
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -71,6 +71,14 @@ ifneq ($(CONFIG_INPUT_STMPE811_TEMP_DISABLE),y)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BUTTONS),y)
|
||||
CSRCS += button_upper.c
|
||||
ifeq ($(CONFIG_BUTTONS_LOWER),y)
|
||||
CSRCS += button_lower.c
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DJOYSTICK),y)
|
||||
CSRCS += djoystick.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/input/ads7843e.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Diego Sanchez <dsanchez@nx-engineering.com>
|
||||
*
|
||||
|
|
@ -63,6 +63,7 @@
|
|||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
|
@ -94,15 +95,8 @@
|
|||
****************************************************************************/
|
||||
/* Low-level SPI helpers */
|
||||
|
||||
#ifdef CONFIG_SPI_OWNBUS
|
||||
static inline void ads7843e_configspi(FAR struct spi_dev_s *spi);
|
||||
# define ads7843e_lock(spi)
|
||||
# define ads7843e_unlock(spi)
|
||||
#else
|
||||
# define ads7843e_configspi(spi);
|
||||
static void ads7843e_lock(FAR struct spi_dev_s *spi);
|
||||
static void ads7843e_unlock(FAR struct spi_dev_s *spi);
|
||||
#endif
|
||||
|
||||
static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd);
|
||||
|
||||
|
|
@ -180,7 +174,6 @@ static struct ads7843e_dev_s *g_ads7843elist;
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SPI_OWNBUS
|
||||
static void ads7843e_lock(FAR struct spi_dev_s *spi)
|
||||
{
|
||||
/* Lock the SPI bus because there are multiple devices competing for the
|
||||
|
|
@ -197,18 +190,17 @@ static void ads7843e_lock(FAR struct spi_dev_s *spi)
|
|||
SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, true);
|
||||
SPI_SETMODE(spi, CONFIG_ADS7843E_SPIMODE);
|
||||
SPI_SETBITS(spi, 8);
|
||||
SPI_SETFREQUENCY(spi, CONFIG_ADS7843E_FREQUENCY);
|
||||
(void)SPI_HWFEATURES(spi, 0);
|
||||
(void)SPI_SETFREQUENCY(spi, CONFIG_ADS7843E_FREQUENCY);
|
||||
SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ads7843e_unlock
|
||||
*
|
||||
* Description:
|
||||
* If we are sharing the SPI bus with other devices (CONFIG_SPI_OWNBUS
|
||||
* undefined) then we need to un-lock the SPI bus for each transfer,
|
||||
* possibly losing the current configuration.
|
||||
* Un-lock the SPI bus after each transfer, possibly losing the current
|
||||
* configuration if we are sharing the bus with other devices.
|
||||
*
|
||||
* Parameters:
|
||||
* spi - Reference to the SPI driver structure
|
||||
|
|
@ -220,48 +212,12 @@ static void ads7843e_lock(FAR struct spi_dev_s *spi)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SPI_OWNBUS
|
||||
static void ads7843e_unlock(FAR struct spi_dev_s *spi)
|
||||
{
|
||||
/* Relinquish the SPI bus. */
|
||||
|
||||
(void)SPI_LOCK(spi, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: ads7843e_configspi
|
||||
*
|
||||
* Description:
|
||||
* Configure the SPI for use with the ADS7843E. This function should be
|
||||
* called once during touchscreen initialization to configure the SPI
|
||||
* bus. Note that if CONFIG_SPI_OWNBUS is not defined, then this function
|
||||
* does nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* spi - Reference to the SPI driver structure
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SPI_OWNBUS
|
||||
static inline void ads7843e_configspi(FAR struct spi_dev_s *spi)
|
||||
{
|
||||
/* Configure SPI for the ADS7843. But only if we own the SPI bus.
|
||||
* Otherwise, don't bother because it might change.
|
||||
*/
|
||||
|
||||
SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, true);
|
||||
SPI_SETMODE(spi, CONFIG_ADS7843E_SPIMODE);
|
||||
SPI_SETBITS(spi, 8);
|
||||
SPI_SETFREQUENCY(spi, CONFIG_ADS7843E_FREQUENCY);
|
||||
SPI_SELECT(spi, SPIDEV_TOUCHSCREEN, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ads7843e_sendcmd
|
||||
|
|
@ -385,7 +341,7 @@ static int ads7843e_sample(FAR struct ads7843e_dev_s *priv,
|
|||
* from changing until it has been reported.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Is there new ADS7843E sample data available? */
|
||||
|
||||
|
|
@ -395,7 +351,7 @@ static int ads7843e_sample(FAR struct ads7843e_dev_s *priv,
|
|||
* sampled data.
|
||||
*/
|
||||
|
||||
memcpy(sample, &priv->sample, sizeof(struct ads7843e_sample_s ));
|
||||
memcpy(sample, &priv->sample, sizeof(struct ads7843e_sample_s));
|
||||
|
||||
/* Now manage state transitions */
|
||||
|
||||
|
|
@ -420,7 +376,7 @@ static int ads7843e_sample(FAR struct ads7843e_dev_s *priv,
|
|||
ret = OK;
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +399,7 @@ static int ads7843e_waitsample(FAR struct ads7843e_dev_s *priv,
|
|||
*/
|
||||
|
||||
sched_lock();
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Now release the semaphore that manages mutually exclusive access to
|
||||
* the device structure. This may cause other tasks to become ready to
|
||||
|
|
@ -480,7 +436,7 @@ static int ads7843e_waitsample(FAR struct ads7843e_dev_s *priv,
|
|||
|
||||
ivdbg("Sampled\n");
|
||||
|
||||
/* Re-acquire the semaphore that manages mutually exclusive access to
|
||||
/* Re-acquire the semaphore that manages mutually exclusive access to
|
||||
* the device structure. We may have to wait here. But we have our sample.
|
||||
* Interrupts and pre-emption will be re-enabled while we wait.
|
||||
*/
|
||||
|
|
@ -493,7 +449,7 @@ errout:
|
|||
* have pre-emption disabled.
|
||||
*/
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Restore pre-emption. We might get suspended here but that is okay
|
||||
* because we already have our sample. Note: this means that if there
|
||||
|
|
@ -974,10 +930,10 @@ static ssize_t ads7843e_read(FAR struct file *filep, FAR char *buffer, size_t le
|
|||
|
||||
if (sample.contact == CONTACT_UP)
|
||||
{
|
||||
/* Pen is now up. Is the positional data valid? This is important to
|
||||
* know because the release will be sent to the window based on its
|
||||
* last positional data.
|
||||
*/
|
||||
/* Pen is now up. Is the positional data valid? This is important to
|
||||
* know because the release will be sent to the window based on its
|
||||
* last positional data.
|
||||
*/
|
||||
|
||||
if (sample.valid)
|
||||
{
|
||||
|
|
@ -1252,10 +1208,6 @@ int ads7843e_register(FAR struct spi_dev_s *spi,
|
|||
|
||||
ads7843e_lock(spi);
|
||||
|
||||
/* Configure the SPI interface */
|
||||
|
||||
ads7843e_configspi(spi);
|
||||
|
||||
/* Enable the PEN IRQ */
|
||||
|
||||
ads7843e_sendcmd(priv, ADS7843_CMD_ENABPENIRQ);
|
||||
|
|
@ -1284,7 +1236,7 @@ int ads7843e_register(FAR struct spi_dev_s *spi,
|
|||
#ifdef CONFIG_ADS7843E_MULTIPLE
|
||||
priv->flink = g_ads7843elist;
|
||||
g_ads7843elist = priv;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
#endif
|
||||
|
||||
/* Schedule work to perform the initial sampling and to set the data
|
||||
|
|
|
|||
|
|
@ -61,17 +61,17 @@
|
|||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/input/ajoystick.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure provides the state of one discrete joystick driver */
|
||||
/* This structure provides the state of one analog joystick driver */
|
||||
|
||||
struct ajoy_upperhalf_s
|
||||
{
|
||||
/* Saved binding to the lower half discrete joystick driver */
|
||||
/* Saved binding to the lower half analog joystick driver */
|
||||
|
||||
FAR const struct ajoy_lowerhalf_s *au_lower;
|
||||
|
||||
|
|
@ -143,7 +143,8 @@ static void ajoy_sample(FAR struct ajoy_upperhalf_s *priv);
|
|||
|
||||
static int ajoy_open(FAR struct file *filep);
|
||||
static int ajoy_close(FAR struct file *filep);
|
||||
static ssize_t ajoy_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t ajoy_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int ajoy_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
|
|
@ -215,7 +216,7 @@ static void ajoy_enable(FAR struct ajoy_upperhalf_s *priv)
|
|||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Visit each opened reference to the device */
|
||||
|
||||
|
|
@ -265,7 +266,7 @@ static void ajoy_enable(FAR struct ajoy_upperhalf_s *priv)
|
|||
lower->al_enable(lower, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ static void ajoy_sample(FAR struct ajoy_upperhalf_s *priv)
|
|||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Sample the new button state */
|
||||
|
||||
|
|
@ -385,7 +386,7 @@ static void ajoy_sample(FAR struct ajoy_upperhalf_s *priv)
|
|||
#endif
|
||||
|
||||
priv->au_sample = sample;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -484,10 +485,10 @@ static int ajoy_close(FAR struct file *filep)
|
|||
* detection anyway.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
closing = opriv->ao_closing;
|
||||
opriv->ao_closing = true;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (closing)
|
||||
{
|
||||
|
|
@ -822,15 +823,15 @@ errout_with_dusem:
|
|||
* Name: ajoy_register
|
||||
*
|
||||
* Description:
|
||||
* Bind the lower half discrete joystick driver to an instance of the
|
||||
* upper half discrete joystick driver and register the composite character
|
||||
* Bind the lower half analog joystick driver to an instance of the
|
||||
* upper half analog joystick driver and register the composite character
|
||||
* driver as the specific device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devname - The name of the discrete joystick device to be registers.
|
||||
* devname - The name of the analog joystick device to be registers.
|
||||
* This should be a string of the form "/priv/ajoyN" where N is the the
|
||||
* minor device number.
|
||||
* lower - An instance of the platform-specific discrete joystick lower
|
||||
* lower - An instance of the platform-specific analog joystick lower
|
||||
* half driver.
|
||||
*
|
||||
* Returned Values:
|
||||
|
|
|
|||
237
drivers/input/button_lower.c
Normal file
237
drivers/input/button_lower.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/****************************************************************************
|
||||
* drivers/input/button_lower.c
|
||||
*
|
||||
* Copyright (C) 2015 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/input/buttons.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#undef __KERNEL__
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#if CONFIG_BUTTONS_LOWER
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static btn_buttonset_t btn_supported(FAR const struct btn_lowerhalf_s *lower);
|
||||
static btn_buttonset_t btn_buttons(FAR const struct btn_lowerhalf_s *lower);
|
||||
static void btn_enable(FAR const struct btn_lowerhalf_s *lower,
|
||||
btn_buttonset_t press, btn_buttonset_t release,
|
||||
btn_handler_t handler, FAR void *arg);
|
||||
|
||||
static void btn_disable(void);
|
||||
static int btn_interrupt(int irq, FAR void *context);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the button button lower half driver interface */
|
||||
|
||||
static const struct btn_lowerhalf_s g_btnlower =
|
||||
{
|
||||
.bl_supported = btn_supported,
|
||||
.bl_buttons = btn_buttons,
|
||||
.bl_enable = btn_enable,
|
||||
};
|
||||
|
||||
/* Current interrupt handler and argument */
|
||||
|
||||
static btn_handler_t g_btnhandler;
|
||||
static FAR void *g_btnarg;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_supported
|
||||
*
|
||||
* Description:
|
||||
* Return the set of buttons supported
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static btn_buttonset_t btn_supported(FAR const struct btn_lowerhalf_s *lower)
|
||||
{
|
||||
ivdbg("NUM_BUTTONS: %02x\n", NUM_BUTTONS);
|
||||
return (btn_buttonset_t)((1 << NUM_BUTTONS) - 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_buttons
|
||||
*
|
||||
* Description:
|
||||
* Return the current state of button data
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static btn_buttonset_t btn_buttons(FAR const struct btn_lowerhalf_s *lower)
|
||||
{
|
||||
return board_buttons();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_enable
|
||||
*
|
||||
* Description:
|
||||
* Enable interrupts on the selected set of buttons. And empty set or
|
||||
* a NULL handler will disable all interrupts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btn_enable(FAR const struct btn_lowerhalf_s *lower,
|
||||
btn_buttonset_t press, btn_buttonset_t release,
|
||||
btn_handler_t handler, FAR void *arg)
|
||||
{
|
||||
btn_buttonset_t mask;
|
||||
btn_buttonset_t either = press | release;
|
||||
irqstate_t flags;
|
||||
int id;
|
||||
|
||||
/* Start with all interrupts disabled */
|
||||
|
||||
flags = enter_critical_section();
|
||||
btn_disable();
|
||||
|
||||
illvdbg("press: %02x release: %02x handler: %p arg: %p\n",
|
||||
press, release, handler, arg);
|
||||
|
||||
/* If no events are indicated or if no handler is provided, then this
|
||||
* must really be a request to disable interrupts.
|
||||
*/
|
||||
|
||||
if (either && handler)
|
||||
{
|
||||
/* Save the new the handler and argument */
|
||||
|
||||
g_btnhandler = handler;
|
||||
g_btnarg = arg;
|
||||
|
||||
/* Attach and enable each button interrupt */
|
||||
|
||||
for (id = 0; id < NUM_BUTTONS; id++)
|
||||
{
|
||||
mask = (1 << id);
|
||||
if ((either & mask) != 0)
|
||||
{
|
||||
(void)board_button_irq(id, btn_interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_disable
|
||||
*
|
||||
* Description:
|
||||
* Disable all button interrupts
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btn_disable(void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
int id;
|
||||
|
||||
/* Disable each button interrupt */
|
||||
|
||||
flags = enter_critical_section();
|
||||
for (id = 0; id < NUM_BUTTONS; id++)
|
||||
{
|
||||
(void)board_button_irq(id, NULL);
|
||||
}
|
||||
|
||||
/* Nullify the handler and argument */
|
||||
|
||||
g_btnhandler = NULL;
|
||||
g_btnarg = NULL;
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_interrupt
|
||||
*
|
||||
* Description:
|
||||
* Discrete button interrupt handler (all buttons)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int btn_interrupt(int irq, FAR void *context)
|
||||
{
|
||||
DEBUGASSERT(g_btnhandler);
|
||||
|
||||
if (g_btnhandler)
|
||||
{
|
||||
g_btnhandler(&g_btnlower, g_btnarg);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_lower_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the generic button lower half driver, bind it and register
|
||||
* it with the upper half button driver as devname.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btn_lower_initialize(FAR const char *devname)
|
||||
{
|
||||
board_button_initialize();
|
||||
return btn_register(devname, &g_btnlower);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BUTTONS_LOWER */
|
||||
882
drivers/input/button_upper.c
Normal file
882
drivers/input/button_upper.c
Normal file
|
|
@ -0,0 +1,882 @@
|
|||
/****************************************************************************
|
||||
* drivers/input/button_upper.c
|
||||
*
|
||||
* Copyright (C) 2015 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* This file provides a driver for a button input devices.
|
||||
*
|
||||
* The buttons driver exports a standard character driver interface. By
|
||||
* convention, the button driver is registered as an input device at
|
||||
* /dev/btnN where N uniquely identifies the driver instance.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/input/buttons.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure provides the state of one button driver */
|
||||
|
||||
struct btn_upperhalf_s
|
||||
{
|
||||
/* Saved binding to the lower half button driver */
|
||||
|
||||
FAR const struct btn_lowerhalf_s *bu_lower;
|
||||
|
||||
btn_buttonset_t bu_enabled; /* Set of currently enabled button interrupts */
|
||||
btn_buttonset_t bu_sample; /* Last sampled button states */
|
||||
sem_t bu_exclsem; /* Supports exclusive access to the device */
|
||||
|
||||
/* The following is a singly linked list of open references to the
|
||||
* button device.
|
||||
*/
|
||||
|
||||
FAR struct btn_open_s *bu_open;
|
||||
};
|
||||
|
||||
/* This structure describes the state of one open button driver instance */
|
||||
|
||||
struct btn_open_s
|
||||
{
|
||||
/* Supports a singly linked list */
|
||||
|
||||
FAR struct btn_open_s *bo_flink;
|
||||
|
||||
/* The following will be true if we are closing */
|
||||
|
||||
volatile bool bo_closing;
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
/* Button event notification information */
|
||||
|
||||
pid_t bo_pid;
|
||||
struct btn_notify_s bo_notify;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
/* Poll event information */
|
||||
|
||||
struct btn_pollevents_s bo_pollevents;
|
||||
|
||||
/* The following is a list if poll structures of threads waiting for
|
||||
* driver events.
|
||||
*/
|
||||
|
||||
FAR struct pollfd *bo_fds[CONFIG_BUTTONS_NPOLLWAITERS];
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Semaphore helpers */
|
||||
|
||||
static inline int btn_takesem(sem_t *sem);
|
||||
#define btn_givesem(s) sem_post(s);
|
||||
|
||||
/* Sampling and Interrupt handling */
|
||||
|
||||
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
|
||||
static void btn_enable(FAR struct btn_upperhalf_s *priv);
|
||||
static void btn_interrupt(FAR const struct btn_lowerhalf_s *lower,
|
||||
FAR void *arg);
|
||||
#endif
|
||||
|
||||
/* Sampling */
|
||||
|
||||
static void btn_sample(FAR struct btn_upperhalf_s *priv);
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
static int btn_open(FAR struct file *filep);
|
||||
static int btn_close(FAR struct file *filep);
|
||||
static ssize_t btn_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int btn_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int btn_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations btn_fops =
|
||||
{
|
||||
btn_open, /* open */
|
||||
btn_close, /* close */
|
||||
btn_read, /* read */
|
||||
0, /* write */
|
||||
0, /* seek */
|
||||
btn_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, btn_poll /* poll */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_takesem
|
||||
****************************************************************************/
|
||||
|
||||
static inline int btn_takesem(sem_t *sem)
|
||||
{
|
||||
/* Take a count from the semaphore, possibly waiting */
|
||||
|
||||
if (sem_wait(sem) < 0)
|
||||
{
|
||||
/* EINTR is the only error that we expect */
|
||||
|
||||
int errcode = get_errno();
|
||||
DEBUGASSERT(errcode == EINTR);
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_enable
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
|
||||
static void btn_enable(FAR struct btn_upperhalf_s *priv)
|
||||
{
|
||||
FAR const struct btn_lowerhalf_s *lower = priv->bu_lower;
|
||||
FAR struct btn_open_s *opriv;
|
||||
btn_buttonset_t press;
|
||||
btn_buttonset_t release;
|
||||
irqstate_t flags;
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int i;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(priv && priv->bu_lower);
|
||||
lower = priv->bu_lower;
|
||||
|
||||
/* This routine is called both task level and interrupt level, so
|
||||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Visit each opened reference to the device */
|
||||
|
||||
press = 0;
|
||||
release = 0;
|
||||
|
||||
for (opriv = priv->bu_open; opriv; opriv = opriv->bo_flink)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
/* Are there any poll waiters? */
|
||||
|
||||
for (i = 0; i < CONFIG_BUTTONS_NPOLLWAITERS; i++)
|
||||
{
|
||||
if (opriv->bo_fds[i])
|
||||
{
|
||||
/* Yes.. OR in the poll event buttons */
|
||||
|
||||
press |= opriv->bo_pollevents.ap_press;
|
||||
release |= opriv->bo_pollevents.ap_release;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
/* OR in the signal events */
|
||||
|
||||
press |= opriv->bo_notify.bn_press;
|
||||
release |= opriv->bo_notify.bn_release;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable/disable button interrupts */
|
||||
|
||||
DEBUGASSERT(lower->bl_enable);
|
||||
if (press != 0 || release != 0)
|
||||
{
|
||||
/* Enable interrupts with the new button set */
|
||||
|
||||
lower->bl_enable(lower, press, release,
|
||||
(btn_handler_t)btn_interrupt, priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable further interrupts */
|
||||
|
||||
lower->bl_enable(lower, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_interrupt
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
|
||||
static void btn_interrupt(FAR const struct btn_lowerhalf_s *lower,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct btn_upperhalf_s *priv = (FAR struct btn_upperhalf_s *)arg;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Process the next sample */
|
||||
|
||||
btn_sample(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_sample
|
||||
****************************************************************************/
|
||||
|
||||
static void btn_sample(FAR struct btn_upperhalf_s *priv)
|
||||
{
|
||||
FAR const struct btn_lowerhalf_s *lower = priv->bu_lower;
|
||||
FAR struct btn_open_s *opriv;
|
||||
btn_buttonset_t sample;
|
||||
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
|
||||
btn_buttonset_t change;
|
||||
btn_buttonset_t press;
|
||||
btn_buttonset_t release;
|
||||
#endif
|
||||
irqstate_t flags;
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int i;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(priv && priv->bu_lower);
|
||||
lower = priv->bu_lower;
|
||||
|
||||
/* This routine is called both task level and interrupt level, so
|
||||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Sample the new button state */
|
||||
|
||||
DEBUGASSERT(lower->bl_buttons);
|
||||
sample = lower->bl_buttons(lower);
|
||||
|
||||
#if !defined(CONFIG_DISABLE_POLL) || !defined(CONFIG_DISABLE_SIGNALS)
|
||||
/* Determine which buttons have been newly pressed and which have been
|
||||
* newly released.
|
||||
*/
|
||||
|
||||
change = sample ^ priv->bu_sample;
|
||||
press = change & sample;
|
||||
|
||||
DEBUGASSERT(lower->bl_supported);
|
||||
release = change & (lower->bl_supported(lower) & ~sample);
|
||||
|
||||
/* Visit each opened reference to the device */
|
||||
|
||||
for (opriv = priv->bu_open; opriv; opriv = opriv->bo_flink)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
/* Have any poll events occurred? */
|
||||
|
||||
if ((press & opriv->bo_pollevents.ap_press) != 0 ||
|
||||
(release & opriv->bo_pollevents.ap_release) != 0)
|
||||
{
|
||||
/* Yes.. Notify all waiters */
|
||||
|
||||
for (i = 0; i < CONFIG_BUTTONS_NPOLLWAITERS; i++)
|
||||
{
|
||||
FAR struct pollfd *fds = opriv->bo_fds[i];
|
||||
if (fds)
|
||||
{
|
||||
fds->revents |= (fds->events & POLLIN);
|
||||
if (fds->revents != 0)
|
||||
{
|
||||
ivdbg("Report events: %02x\n", fds->revents);
|
||||
sem_post(fds->sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
/* Have any signal events occurred? */
|
||||
|
||||
if ((press & opriv->bo_notify.bn_press) != 0 ||
|
||||
(release & opriv->bo_notify.bn_release) != 0)
|
||||
{
|
||||
/* Yes.. Signal the waiter */
|
||||
|
||||
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||
union sigval value;
|
||||
value.sival_int = (int)sample;
|
||||
(void)sigqueue(opriv->bo_pid, opriv->bo_notify.bn_signo, value);
|
||||
#else
|
||||
(void)sigqueue(opriv->bo_pid, opriv->bo_notify.dn.signo,
|
||||
(FAR void *)sample);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable/disable interrupt handling */
|
||||
|
||||
btn_enable(priv);
|
||||
#endif
|
||||
|
||||
priv->bu_sample = sample;
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_open
|
||||
****************************************************************************/
|
||||
|
||||
static int btn_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
FAR struct btn_open_s *opriv;
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
FAR const struct btn_lowerhalf_s *lower;
|
||||
btn_buttonset_t supported;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep && filep->f_inode);
|
||||
inode = filep->f_inode;
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = (FAR struct btn_upperhalf_s *)inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver structure */
|
||||
|
||||
ret = btn_takesem(&priv->bu_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: btn_takesem failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate a new open structure */
|
||||
|
||||
opriv = (FAR struct btn_open_s *)kmm_zalloc(sizeof(struct btn_open_s));
|
||||
if (!opriv)
|
||||
{
|
||||
ivdbg("ERROR: Failled to allocate open structure\n");
|
||||
ret = -ENOMEM;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* Initialize the open structure */
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
lower = priv->bu_lower;
|
||||
DEBUGASSERT(lower && lower->bl_supported);
|
||||
supported = lower->bl_supported(lower);
|
||||
|
||||
opriv->bo_pollevents.ap_press = supported;
|
||||
opriv->bo_pollevents.ap_release = supported;
|
||||
#endif
|
||||
|
||||
/* Attach the open structure to the device */
|
||||
|
||||
opriv->bo_flink = priv->bu_open;
|
||||
priv->bu_open = opriv;
|
||||
|
||||
/* Attach the open structure to the file structure */
|
||||
|
||||
filep->f_priv = (FAR void *)opriv;
|
||||
ret = OK;
|
||||
|
||||
errout_with_sem:
|
||||
btn_givesem(&priv->bu_exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_close
|
||||
****************************************************************************/
|
||||
|
||||
static int btn_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
FAR struct btn_open_s *opriv;
|
||||
FAR struct btn_open_s *curr;
|
||||
FAR struct btn_open_s *prev;
|
||||
irqstate_t flags;
|
||||
bool closing;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep && filep->f_priv && filep->f_inode);
|
||||
opriv = filep->f_priv;
|
||||
inode = filep->f_inode;
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = (FAR struct btn_upperhalf_s *)inode->i_private;
|
||||
|
||||
/* Handle an improbable race conditions with the following atomic test
|
||||
* and set.
|
||||
*
|
||||
* This is actually a pretty feeble attempt to handle this. The
|
||||
* improbable race condition occurs if two different threads try to
|
||||
* close the button driver at the same time. The rule: don't do
|
||||
* that! It is feeble because we do not really enforce stale pointer
|
||||
* detection anyway.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
closing = opriv->bo_closing;
|
||||
opriv->bo_closing = true;
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (closing)
|
||||
{
|
||||
/* Another thread is doing the close */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the driver structure */
|
||||
|
||||
ret = btn_takesem(&priv->bu_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: btn_takesem failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Find the open structure in the list of open structures for the device */
|
||||
|
||||
for (prev = NULL, curr = priv->bu_open;
|
||||
curr && curr != opriv;
|
||||
prev = curr, curr = curr->bo_flink);
|
||||
|
||||
DEBUGASSERT(curr);
|
||||
if (!curr)
|
||||
{
|
||||
ivdbg("ERROR: Failed to find open entry\n");
|
||||
ret = -ENOENT;
|
||||
goto errout_with_exclsem;
|
||||
}
|
||||
|
||||
/* Remove the structure from the device */
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->bo_flink = opriv->bo_flink;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->bu_open = opriv->bo_flink;
|
||||
}
|
||||
|
||||
/* And free the open structure */
|
||||
|
||||
kmm_free(opriv);
|
||||
|
||||
/* Enable/disable interrupt handling */
|
||||
|
||||
btn_enable(priv);
|
||||
ret = OK;
|
||||
|
||||
errout_with_exclsem:
|
||||
btn_givesem(&priv->bu_exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t btn_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
FAR const struct btn_lowerhalf_s *lower;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep && filep->f_inode);
|
||||
inode = filep->f_inode;
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = (FAR struct btn_upperhalf_s *)inode->i_private;
|
||||
|
||||
/* Make sure that the buffer is sufficiently large to hold at least one
|
||||
* complete sample.
|
||||
*
|
||||
* REVISIT: Should also check buffer alignment.
|
||||
*/
|
||||
|
||||
if (len < sizeof(btn_buttonset_t))
|
||||
{
|
||||
ivdbg("ERROR: buffer too small: %lu\n", (unsigned long)len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the driver structure */
|
||||
|
||||
ret = btn_takesem(&priv->bu_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: btn_takesem failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read and return the current state of the buttons */
|
||||
|
||||
lower = priv->bu_lower;
|
||||
DEBUGASSERT(lower && lower->bl_buttons);
|
||||
*(FAR btn_buttonset_t *)buffer = lower->bl_buttons(lower);
|
||||
|
||||
btn_givesem(&priv->bu_exclsem);
|
||||
return (ssize_t)sizeof(btn_buttonset_t);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int btn_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
FAR struct btn_open_s *opriv;
|
||||
FAR const struct btn_lowerhalf_s *lower;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep && filep->f_priv && filep->f_inode);
|
||||
opriv = filep->f_priv;
|
||||
inode = filep->f_inode;
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = (FAR struct btn_upperhalf_s *)inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver structure */
|
||||
|
||||
ret = btn_takesem(&priv->bu_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: btn_takesem failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Handle the ioctl command */
|
||||
|
||||
ret = -EINVAL;
|
||||
switch (cmd)
|
||||
{
|
||||
/* Command: BTNIOC_SUPPORTED
|
||||
* Description: Report the set of button events supported by the hardware;
|
||||
* Argument: A pointer to writeable integer value in which to return the
|
||||
* set of supported buttons.
|
||||
* Return: Zero (OK) on success. Minus one will be returned on failure
|
||||
* with the errno value set appropriately.
|
||||
*/
|
||||
|
||||
case BTNIOC_SUPPORTED:
|
||||
{
|
||||
FAR btn_buttonset_t *supported = (FAR btn_buttonset_t *)((uintptr_t)arg);
|
||||
|
||||
if (supported)
|
||||
{
|
||||
lower = priv->bu_lower;
|
||||
DEBUGASSERT(lower && lower->bl_supported);
|
||||
|
||||
*supported = lower->bl_supported(lower);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
/* Command: BTNIOC_POLLEVENTS
|
||||
* Description: Specify the set of button events that can cause a poll()
|
||||
* to awaken. The default is all button depressions and
|
||||
* all button releases (all supported buttons);
|
||||
* Argument: A read-only pointer to an instance of struct
|
||||
* btn_pollevents_s
|
||||
* Return: Zero (OK) on success. Minus one will be returned on
|
||||
* failure with the errno value set appropriately.
|
||||
*/
|
||||
|
||||
case BTNIOC_POLLEVENTS:
|
||||
{
|
||||
FAR struct btn_pollevents_s *pollevents =
|
||||
(FAR struct btn_pollevents_s *)((uintptr_t)arg);
|
||||
|
||||
if (pollevents)
|
||||
{
|
||||
/* Save the poll events */
|
||||
|
||||
opriv->bo_pollevents.ap_press = pollevents->ap_press;
|
||||
opriv->bo_pollevents.ap_release = pollevents->ap_release;
|
||||
|
||||
/* Enable/disable interrupt handling */
|
||||
|
||||
btn_enable(priv);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
/* Command: BTNIOC_REGISTER
|
||||
* Description: Register to receive a signal whenever there is a change
|
||||
* in any of the discrete buttone inputs. This feature,
|
||||
* of course, depends upon interrupt GPIO support from the
|
||||
* platform.
|
||||
* Argument: A read-only pointer to an instance of struct
|
||||
* btn_notify_s
|
||||
* Return: Zero (OK) on success. Minus one will be returned on
|
||||
* failure with the errno value set appropriately.
|
||||
*/
|
||||
|
||||
case BTNIOC_REGISTER:
|
||||
{
|
||||
FAR struct btn_notify_s *notify =
|
||||
(FAR struct btn_notify_s *)((uintptr_t)arg);
|
||||
|
||||
if (notify)
|
||||
{
|
||||
/* Save the notification events */
|
||||
|
||||
opriv->bo_notify.bn_press = notify->bn_press;
|
||||
opriv->bo_notify.bn_release = notify->bn_release;
|
||||
opriv->bo_notify.bn_signo = notify->bn_signo;
|
||||
opriv->bo_pid = getpid();
|
||||
|
||||
/* Enable/disable interrupt handling */
|
||||
|
||||
btn_enable(priv);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ivdbg("ERROR: Unrecognized command: %ld\n", cmd);
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
btn_givesem(&priv->bu_exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_poll
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int btn_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
FAR struct btn_open_s *opriv;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(filep && filep->f_priv && filep->f_inode);
|
||||
opriv = filep->f_priv;
|
||||
inode = filep->f_inode;
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = (FAR struct btn_upperhalf_s *)inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver structure */
|
||||
|
||||
ret = btn_takesem(&priv->bu_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: btn_takesem failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Are we setting up the poll? Or tearing it down? */
|
||||
|
||||
if (setup)
|
||||
{
|
||||
/* This is a request to set up the poll. Find an available
|
||||
* slot for the poll structure reference
|
||||
*/
|
||||
|
||||
for (i = 0; i < CONFIG_BUTTONS_NPOLLWAITERS; i++)
|
||||
{
|
||||
/* Find an available slot */
|
||||
|
||||
if (!opriv->bo_fds[i])
|
||||
{
|
||||
/* Bind the poll structure and this slot */
|
||||
|
||||
opriv->bo_fds[i] = fds;
|
||||
fds->priv = &opriv->bo_fds[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= CONFIG_BUTTONS_NPOLLWAITERS)
|
||||
{
|
||||
ivdbg("ERROR: Too man poll waiters\n");
|
||||
fds->priv = NULL;
|
||||
ret = -EBUSY;
|
||||
goto errout_with_dusem;
|
||||
}
|
||||
}
|
||||
else if (fds->priv)
|
||||
{
|
||||
/* This is a request to tear down the poll. */
|
||||
|
||||
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!slot)
|
||||
{
|
||||
ivdbg("ERROR: Poll slot not found\n");
|
||||
ret = -EIO;
|
||||
goto errout_with_dusem;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Remove all memory of the poll setup */
|
||||
|
||||
*slot = NULL;
|
||||
fds->priv = NULL;
|
||||
}
|
||||
|
||||
errout_with_dusem:
|
||||
btn_givesem(&priv->bu_exclsem);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btn_register
|
||||
*
|
||||
* Description:
|
||||
* Bind the lower half button driver to an instance of the upper half
|
||||
* button driver and register the composite character driver as the
|
||||
* specified device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devname - The name of the button device to be registered.
|
||||
* This should be a string of the form "/dev/btnN" where N is the the
|
||||
* minor device number.
|
||||
* lower - An instance of the platform-specific button lower half driver.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success. Otherwise a negated errno value is
|
||||
* returned to indicate the nature of the failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btn_register(FAR const char *devname,
|
||||
FAR const struct btn_lowerhalf_s *lower)
|
||||
|
||||
{
|
||||
FAR struct btn_upperhalf_s *priv;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(devname && lower);
|
||||
|
||||
/* Allocate a new button driver instance */
|
||||
|
||||
priv = (FAR struct btn_upperhalf_s *)
|
||||
kmm_zalloc(sizeof(struct btn_upperhalf_s));
|
||||
|
||||
if (!priv)
|
||||
{
|
||||
ivdbg("ERROR: Failed to allocate device structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Make sure that all button interrupts are disabled */
|
||||
|
||||
DEBUGASSERT(lower->bl_enable);
|
||||
lower->bl_enable(lower, 0, 0, NULL, NULL);
|
||||
|
||||
/* Initialize the new button driver instance */
|
||||
|
||||
priv->bu_lower = lower;
|
||||
sem_init(&priv->bu_exclsem, 0, 1);
|
||||
|
||||
DEBUGASSERT(lower->bl_buttons);
|
||||
priv->bu_sample = lower->bl_buttons(lower);
|
||||
|
||||
/* And register the button driver */
|
||||
|
||||
ret = register_driver(devname, &btn_fops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
ivdbg("ERROR: register_driver failed: %d\n", ret);
|
||||
goto errout_with_priv;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_priv:
|
||||
sem_destroy(&priv->bu_exclsem);
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/input/djoystick.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
|
|
@ -143,7 +143,8 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv);
|
|||
|
||||
static int djoy_open(FAR struct file *filep);
|
||||
static int djoy_close(FAR struct file *filep);
|
||||
static ssize_t djoy_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t djoy_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int djoy_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
|
|
@ -215,7 +216,7 @@ static void djoy_enable(FAR struct djoy_upperhalf_s *priv)
|
|||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Visit each opened reference to the device */
|
||||
|
||||
|
|
@ -265,7 +266,7 @@ static void djoy_enable(FAR struct djoy_upperhalf_s *priv)
|
|||
lower->dl_enable(lower, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv)
|
|||
* interrupts must be disabled.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Sample the new button state */
|
||||
|
||||
|
|
@ -385,7 +386,7 @@ static void djoy_sample(FAR struct djoy_upperhalf_s *priv)
|
|||
#endif
|
||||
|
||||
priv->du_sample = sample;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -484,10 +485,10 @@ static int djoy_close(FAR struct file *filep)
|
|||
* detection anyway.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
flags = enter_critical_section();
|
||||
closing = opriv->do_closing;
|
||||
opriv->do_closing = true;
|
||||
irqrestore(flags);
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (closing)
|
||||
{
|
||||
|
|
@ -585,7 +586,7 @@ static ssize_t djoy_read(FAR struct file *filep, FAR char *buffer,
|
|||
lower = priv->du_lower;
|
||||
DEBUGASSERT(lower && lower->dl_sample);
|
||||
priv->du_sample = lower->dl_sample(lower);
|
||||
*(djoy_buttonset_t*)buffer = priv->du_sample;
|
||||
*(FAR djoy_buttonset_t *)buffer = priv->du_sample;
|
||||
ret = sizeof(djoy_buttonset_t);
|
||||
|
||||
djoy_givesem(&priv->du_exclsem);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue