Merged patacongo/nuttx into master

This commit is contained in:
David Sidrane 2016-03-17 11:41:26 -10:00
commit b66405df31
1532 changed files with 70287 additions and 21010 deletions

811
ChangeLog
View file

@ -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).

View file

@ -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

View file

@ -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
View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

File diff suppressed because it is too large Load diff

270
TODO
View file

@ -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

@ -1 +1 @@
Subproject commit 6190d664666b19580969c4e620646ef4e54f0182
Subproject commit feb41dfa8e178a1194fd17afae154bc55912993d

10
audio/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
/Make.dep
/.depend
/*.asm
/*.obj
/*.rel
/*.lst
/*.sym
/*.adb
/*.lib
/*.src

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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
View 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 */

View file

@ -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)
{

View file

@ -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
****************************************************************************/

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -46,7 +46,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h"
#include "binfmt.h"
#ifndef CONFIG_BINFMT_DISABLE

View file

@ -46,7 +46,7 @@
#include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h"
#include "binfmt.h"
#ifndef CONFIG_BINFMT_DISABLE

View file

@ -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;
}

View file

@ -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 */

View file

@ -46,7 +46,7 @@
#include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h"
#include "binfmt.h"
#ifndef CONFIG_BINFMT_DISABLE

View file

@ -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;
}

View file

@ -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

View file

@ -49,11 +49,7 @@
#include <nuttx/binfmt/elf.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
* Public Function Prototypes
****************************************************************************/
/****************************************************************************

View file

@ -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);
}
/****************************************************************************

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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++)
{

View file

@ -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;

View file

@ -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);

View file

@ -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);
}
/****************************************************************************

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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
------------------

View file

@ -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)
{

View file

@ -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;
}

@ -1 +1 @@
Subproject commit ac4035687c824bb4a573e06feb017cb4f3ce7626
Subproject commit f7c42ff4a006f5d37fa6a818aafaf20886309fd1

View file

@ -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

View file

@ -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
View 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);
}

View file

@ -77,7 +77,7 @@ int up_cryptoinitialize(void)
}
#endif
#if CONFIG_CRYPTO_ALGTEST
#ifdef CONFIG_CRYPTO_ALGTEST
res = crypto_test();
if (res)
{

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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 */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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.
*/

View file

@ -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

View file

@ -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);

View file

@ -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 = &regaddr;
msg[0].length = 1;
msg[0].frequency = priv->lower->frequency;
msg[0].addr = priv->lower->address;
msg[0].flags = 0;
msg[0].buffer = &regaddr;
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.
*/

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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
****************************************************************************/

View file

@ -44,7 +44,7 @@
#include <assert.h>
#include <debug.h>
#include "bch_internal.h"
#include "bch.h"
/****************************************************************************
* Pre-processor Definitions

View file

@ -52,7 +52,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include "bch_internal.h"
#include "bch.h"
/****************************************************************************
* Pre-processor Definitions

View file

@ -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);

View file

@ -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;

View file

@ -43,7 +43,7 @@
#include <assert.h>
#include <debug.h>
#include "bch_internal.h"
#include "bch.h"
/****************************************************************************
* Pre-processor Definitions

View file

@ -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");

View file

@ -47,7 +47,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include "bch_internal.h"
#include "bch.h"
/****************************************************************************
* Private Types

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View 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 */

View 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;
}

View file

@ -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