Merge branch 'master' of bitbucket.org:AVyhovanec/nuttx

This commit is contained in:
Aleksandr Vyhovanec 2016-12-30 09:18:53 +03:00
commit 872adef2dc
651 changed files with 9263 additions and 18204 deletions

384
ChangeLog
View File

@ -3130,7 +3130,7 @@
point numbers.
* lib/stdio/lib_libdtoa.c and lib_libvsprintf.c: Correct some floating
point options.
* arch/arm/lpc43xx/lpc32_usb0dev.c: Add framework for development of
* arch/arm/lpc43xx/lpc43_usb0dev.c: Add framework for development of
an USB0, device-side driver for the LPC43XX. The initial check-in,
however, is simply for the LPC31xx driver with name changes. The
LPC31xx has the same USB IP, but will require some additional initialization
@ -4440,7 +4440,7 @@
* binfmt/binfmt_execmodule.c: Here is a place where I forget
to update the call to sched_releasetcb() to pass the thread
type as the second parameter (2013-03-23).
* arch/arm/src/lm, kinetis, lpc32, and nuc1xx: Add kernel build
* arch/arm/src/lm, kinetis, lpc43, and nuc1xx: Add kernel build
support to all ARMv7-M and ARMv6-M chips. There are no
configurations in place to to verify these additions!
(2013-03-24).
@ -10964,7 +10964,7 @@
(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
* arch/arm/src/lpc43xx/lpc43_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
@ -12348,7 +12348,7 @@
adds DEBUGASSERT for invalid geometry and additional memory debug
logic. Also fixes the dangling pointer on error bug. From Ken
Pettit (2016-07-14).
* arch/arm/src/lpc32xx: Extend LPC43xx EMC code to support SDRAM on a
* arch/arm/src/lpc43xx: Extend LPC43xx EMC code to support SDRAM on a
dynamic memory interface. From Vytautas Lukenskas (2016-07-19).
* arch/sim/src: Add the simulated QSPI (N25Q) flash to the simulation
and modify sim up_spiflash.c to enable it to run with different MTD
@ -12772,6 +12772,9 @@
* STM32 DMA2D: fix an error in up_dma2dcreatelayer where an invalid
pointer was returned when a certain underlying function failed. From
Jens Gräf (2016-10-07).
7.19 2016-12-26 Gregory Nutt <gnutt@nuttx.org>
* include/nuttx/fs/nxffs.h: Needs forward reference to struct mtd_dev_s
and needs to include stdbool.h (2016-10-09).
* STM32F103 Minimum: Note in Kconfig that the board supports buttons.
@ -12844,16 +12847,16 @@
(2016-10-19).
* libc/locale: Allows c++ code to compile with or without
CONFIG_LIBC_LOCALE and will generate a link error if CONFIG_LIBC_LOCALE
is not defined and setlocale is referneced. With CONFIG_LIBC_LOCALE
is not defined and setlocale is referenced. With CONFIG_LIBC_LOCALE
defined setlocale will act as if MB string is not supported and return
"C" for POSIX. C and "". From David Sidrane (2016-10-19).
* Add vectors for interrupt levels 2-6 (2016-10-20).
* strtof: Add strtof() as simply a copy of strtod with types and
* Xtensa ESP32: Add vectors for interrupt levels 2-6 (2016-10-20).
* strtof(): Add strtof() as simply a copy of strtod with types and
limits changed (2016-10-20).
* arch/arm/src/stm32v7: Register the watchdog device at the configured
device path CONFIG_WATCHDOG_DEVPATH vs. hard-coded /dev/wdt. From Frank
Benkert (2016-10-21).
* configs/*/defdonf The buttons example was changed to archbuttons. As
* configs/*/defconfig: The buttons example was changed to archbuttons. As
a result all of the button configurations are broken and need some
renaming in the defconfig files. Noted by Frank Berkert (2016-10-21).
* configs/stm32f103-minimum: Add support to PWM on STM32F103-Minimum
@ -12909,7 +12912,7 @@
found in the F4. From David Sidrane (2016-10-26).
* arch/arm/src/stm32f7: stm32f76xx77xx_pinmap.h Missed one. From
David Sidrane (2016-10-26).
* LPC32xx serial: Fix a typo in ioctl TIOCSRS485 ioctl. From Vytautas
* LPC43xx serial: Fix a typo in ioctl TIOCSRS485 ioctl. From Vytautas
Lukenskas (2016-10-27).
* sched/clock: Correct clock initialization. The correct range for
the month is 0-11 but is entered as 1-12 in the .config file
@ -12919,7 +12922,7 @@
* sched/Kconfig: Add ranges to START_YEAR, MONTH, and DAY (2016-10-28).
* configs/nucleo-f303re: Add STM32 F303RE hello configuration; remove
duplicate setting from board.h. From Marc Rechté (2016-10-18).
* arch/arm/src/lpc32xx: Restore RS485 mode on serial port open (if
* arch/arm/src/lpc43xx: Restore RS485 mode on serial port open (if
RS485 is enabled via menuconfig). From Vytautas Lukenskas (2016-10-28).
* arch/arm/src/stm32f7: otgdev fixed typo. From David Sidrane
(2016-10-28).
@ -12949,14 +12952,12 @@
From Paul A. Patience (2016-11-02).
* drivers/ and drivers/spi: Fix Kconfig warning. This commit moves the
ARCH_HAVE_SPI options outside the check for SPI. Those options don't
depend on SPI, and Kconfig files in arch/ enable them even if SPI isn't
enabled.
Sourcing the driver's Kconfig in drivers/Kconfig only if support for
the driver is enabled prevents us from defining these ARCH_HAVE options
in the driver's Kconfig. We should probably remove the other checks in
drivers/Kconfig and check if the drivers are enabled only in their
Kconfig. From Paul A. Patience (2016-11-02).
depend on SPI, and Kconfig files in arch/ enable them even if SPI
isn't enabled. Source the driver's Kconfig in drivers/Kconfig only
if support for the driver is enabled prevents us from defining these
ARCH_HAVE options in the driver's Kconfig. We should probably remove
the other checks in drivers/Kconfig and check if the drivers are
enabled only in their Kconfig. From Paul A. Patience (2016-11-02).
* Move protoypes for the non-standard include/semaphore.h file to the
non-standard include/nuttx/semaphore.h with the other non-standard
semaphore interfaces (2016-11-02).
@ -13100,7 +13101,7 @@
argument so that there can be additional usage. From Sebastien Lorquet
(2016-11-17).
* All timer lower half drivers. Port Sebastien's changes to all all
other implementations of the timer lower half. Very many just and
other implementations of the timer lower half. Many changes and
untested. Expect some problems. (2016-11-17).
* sched/irq: irq_csection() has a bad assumption in the SMP case. It
assumed that the state of certain variables. That was true on entry
@ -13130,5 +13131,348 @@
So this change adds locking (via enter_critical section) to wdog
expiration logic for the the case if the SMP configuration
(2016-11-18).
* SAM3/4: Add delay between setting and clearing the endpoint RESET bit
in sam_ep_resume(). We need to add a delay between setting and
clearing the endpoint reset bit in SAM_UDP_RSTEP. Without the delay the
USB controller will (may?) not reset the endpoint. If the endpoint is
not being reset, the Data Toggle (DTGLE) bit will not to be cleared
which will cause the next transaction to fail if DTGLE is 1. If that
happens the host will time-out and reset the bus. Adding this delay
may also fix the USBMSC_STALL_RACEWAR in usbmsc_scsi.c, however this
has not been verified yet. From Wolfgang Reißnegger (2016-11-18).
* SAM3/4: Remove unused 'halted' flag in UDP driver. From Wolfgang
Reißnegger (2016-11-18).
* SAM3/4: Remove 'stalled' flag in UDP driver. The flag is not necessary.
The state of the endpoint can be determined using 'epstate' instead.
From Wolfgang Reißnegger (2016-11-18).
* USBMSC: Fix length of mode6 sense reply packet. From Wolfgang
Reißnegger (2016-11-18).
* configs/dk-tm4c129x: Typo fix. From Wolfgang Reißnegger (2016-11-18).
* Typo fix in sam_udp.c. From Wolfgang Reißnegger (2016-11-18).
* STM32: STM32F303xB and STM32F303xC chips have 4 ADCs. From Paul A.
Patience (2016-11-19).
* vfork(): Fix a race condition in the SMP case. Existing logic
depended on the fact that the child would not run until waitpid was
called because the child had the same priority as the parent. BUT
in the SMP case that is not true... the child may run immediately on
a different CPU (2016-11-19).
* arch/: Add option to use low-priority work queue to all Ethernet
drivers in arch that support CONFIG_NET_NOINTS (2016-11-19).
* sched/clock: Correct calculation for the case of Tickless mode with
a 32-bit timer. In that case, the calculation was returning
millisecond accuracy. That is not good when the timer accuracy is < 1
msec. From Rajan Gill (2016-11-19).
* sched/task: task_restart() test not supported on SMP systems. This is
not fully implemented (2016-11-19).
* This commit adds a new internal interfaces and fixes a problem with
three APIs in the SMP configuration. The new internal interface is
sched_cpu_pause(tcb). This function will pause a CPU if the task
associated with 'tcb' is running on that CPU. This allows a different
CPU to modify that OS data stuctures associated with the CPU. When the
other CPU is resumed, those modifications can safely take place. The
three fixes are to handle cases in the SMP configuration where one CPU
does need to make modifications to TCB and data structures on a task
that could be running running on another CPU. Those three cases are
task_delete(), task_restart(), and execution of signal handles. In
all three cases the solutions is basically the same: (1) Call
sched_cpu_pause(tcb) to pause the CPU on which the task is running,
(2) perform the necessary operations, then (3) call up_cpu_resume() to
restart the paused CPU (2016-11-20).
* task_restart: Make sure new task starts with pre-emption disabled and
not in a critical section (2016-11-21).
* Fix a typo in a spinlock macro (2016-11-21).
* Spinlocks: Added capability to provide architecture-specific memory
barriers. This was for i.MX6 but does not help with the SMP problems.
It is still a good feature (2016-11-21).
* Remove a assertion condition that appears to rarely cause false-alarm
assertions. Teported by Petteri Aimonen (2016-11-21).
* The examples/qencoder app was trying to init the encoder by a direct
call into the board, cheating in a local header to declare the normally
unavailable function prototype. From Sebastien Lorquet (2016-11-22).
* configs: All QE encoder files. Last change made timer hard-coded to 3.
Make configurable (2016-11-22).
* configs: Remove all traces of the no-longer existent ARCHBUTTONS
example. Remove all button configurations that depended on the
obsoleted ARCHBUTTON example (2016-11-22).
* nucleo-l476rg: Add better selection of timer (2016-11-22).
* implementation of dumpgpio for stm32l4, was required for pwm debug.
From Sebastien Lorquet (2016-11-22).
* SMP: Add logic to avoid a deadlock condition when CPU1 is hung waiting
for g_cpu_irqlock and CPU0 is waitin for g_cpu_paused (2016-11-22).
* Misoc: Add timer driver. From Ramtin Amin (2016-11-22).
* Misoc: Add commits and warnings about missing caculation of the timer
reload value (2016-11-22).
* SAM3/4: Name of method is now setcallback, not sethandler (2016-11-22).
* sam4s-xplained-pro/nsh: Configuration uses old, improper timer interface.
CONFIG_TIMER disabled in configuration. (2016-11-22).
* sam4s-xplained-pro: Remove obsolete timer initialization logic
(2016-11-22).
* Misoc LM32: Make system timer configurable via CONFIG_USEC_PER_TICK.
From Ramtin Amin (2016-11-23).
* LPC43xx: Add timer driver; configs/bambino-200e: Add support for timer
driver. From Alan Carvalho de Assis (2016-11-23).
* SMP: Fix backward condition in test (2016-11-23).
* ARMv7-A SMP: Add a little logic to signal handling (2016-11-24).
* Misoc LM32: Add signal handling logic. From Ramtin Amin (2016-11-24).
* SMP: Add spin_trylock(). Use this in conditions where other CPUs need
to stopped but we cannot call enter_critical_section (2016-11-24).
* Fix for F1 RTC Clock, tested on F103. From Maciej Wójcik (2016-11-25).
* SMP: Fix yet another potential deadlock (2016-11-25).
* Enable CONFIG_RTC in the hymini-stm32v/nsh2 (kitchensink) config.
From Maciej Wójcik (2016-11-26).
* This adds support for keeping i.MX6 inter-processor communication data
in a non-cached address region (2016-11-26).
* i.MX6: Disable non-cached region support. Add SCU register definitions
(2016-11-26).
* i.MX6: Add some controls to enable SMP cache coherency in SMP mode
(2016-11-26).
* ARMv7-A: Fix some SCU SMP logic (2016-11-26).
* ARMv7-A/i.MX6: Modify handling of the SMP cache coherency
configuration so that it is identical to the steps from the TRM.
Makes no differenct, however (2016-11-27).
* The Smoothie project needs to compile C++ inside config/boardname/src/
to use with High Priority Interruption, then I modified the board
configs Makefile to support it. It works fine for the first time
compilation, but if we execute "touch config/boardname/src/Pin.cxx"
and execute "make" it will not detect that Pin.cxx was modified. I
think there is some other place I should modify, but I didn't find
it. From Alan Carvalho de Assis (2016-11-27).
* ARMv7-A/i.MX6 SMP: Move SMP coherent cache setup to earlier in
initialization of CPUn, n>0 (2016-11-27).
* ARMv7 GIC: SGIs are non-maskable but go through the same path as other,
maskable interrupts. Added logic to serialize SGI processing when
necessary (2016-11-27).
* sched_note: Extend OS instrumentation to include some SMP events
(2016-11-27).
* sched_note: Add spinlock instrumentation; In SMP configurations,
select to log only notes from certain CPUs (2016-11-28).
* Misoc LM3: Add Misoc Ethernet driver. Integrate network support into
configs/misoc/hello. Remove configs/misoc/include/generated directory.
I suppose the the intent now is that this is a symbolic link? DANGER!
This means that you cannot compile this code with first generating
these files a providing a symbolic link to this location! From Ramtin
Amin (2016-11-28).
* Add tools/showsize.sh (2016-11-28).
* configs/misoc: Add a sample directory containing generated sources.
This is really only useful for performing test builds. You really
must generate the Misoc architecture for a real-life build. From
Ramtin Amin (2016-11-28).
* sched_note: Permit spinlock and critical section notes in in-memory
buffer iff sched_not_get() interfaces is disabled (2016-11-28).
* STM32 DAC: Fix shift value whenever there are is a DAC2 and, hence,
up to three interfaces. From Marc Rechté (2016-11-29).
* Back out a debug change that was included in commit (2016-11-29).
* i.MX6: Don't output the alphabet if CONFIG_DEBUG_FEATURES is not set
(2016-11-29).
* Misoc LM32: Add logic to flush/invalidate caches. From Ramtin Amin
(2016-11-29).
* drivers/net/: Adapt all Ethernet drivers to work as though
CONFIG_NET_MULTIBUFFER were set. Remove all references to
CONFIG_NET_MULTIBUFFER (2016-11-29).
* stm32_otghshost: if STM32F446 increase number of channels to 16. From
Janne Rosberg (2016-11-30).
* usbhost_composite: fix end offset in usbhost_copyinterface(). From
Janne Rosberg (2016-11-30).
* usbhost_cdcacm: add CDC_SUBCLASS_ACM and CDC_PROTO_ATM to supported
class and proto. From Janne Rosberg (2016-11-30).
* LPC43 SD/MMC: Correct some git definitions on SMMC control register
in lpc43_sdmmc.h. From Alan Carvalho de Assis (2016-11-30).
* STM32L4: Correct USART1/2 definitions. Use default mbed UART4
settings. From Sebastien Lorquet (2016-12-01).
* boardctl: Add new boardctl() command ,BOARDIOC_NX_START, to start the
NX server as a kernel thread (2016-12-01).
* GPDMA driver for the LPC43xx. The GPDMA block is basically the same
as the LPC17xx. Only the clock configuration is different and LPC43xx
has four different DMA request sources, where LPC17xx has only two.
From Alan Carvalho de Assis (2016-12-01).
* Remove RGMP and RGMP drivers (2016-12-02).
* i.MX6: Add an untested SPI driver taken directly from the i.MX1 port
(2016-12-02).
* Eliminate CONFIG_NO_NOINTS. There is no longer any support for
interrupt level processing of the network stack. Lots of files changed
-> lots of testing needed (2016-12-03).
* Fix DEBUGASSERT() in group_signal.c. From Masayuki Ishikawa
(2016-12-04).
* Add support for the SAM5CMP-DB board. From Masayuki Ishikawa
(2016-12-04).
* SAM3/4: Add SMP support for the dual-core SAM4CM. From Masayuki
Ishikawa (2016-12-04).
* C Library: Allow option to enable IP address conversions even when the
IP address family is not supported (2016-12-04).
* SSD1306: Fix errors in SPI mode configuration. From Gong Darcy
(2016-12-04).
* SAMA5 does not build when executing from SDRAM before board
frequencies are not constant. Rather, the bootloader configures the
clocking and we must derive the clocking from the MCK left by the
bootloader. This means lots more computations. This is untested on
initial commit because I don't have a good PWM test setup right now
(2016-12-04).
* Olimex-LPC1766-STK: Enable procfs in NSH configuration. Automount
/proc on startup (2016-12-05).
* SAM4CMP-DB: Add hooks to auto-mount the procfs file system on startup
in board bring-up logic (2016-12-05).
* Remove all references to BOARDIOC_PWMSETUP and board_pwm_setup()
(2016-12-05).
* Remove all references to BOARDIOC_ADCSETUP and board_adc_setup()
(2016-12-05).
* Added Timers 2-5 and control of SAI and I2S PLLs. From David Sidrane
(2016-12-05).
* Added support for stmf469 SAI and I2S PLL configuration and STM446
fixes. From David Sidrane (2016-12-05).
* Expanded otgfs support to stm32F469 and stm32f446. Added missing bits
definitions, Used stm32F469 and stm32f446 bit definitions, Removed
unsed header file. From David Sidrane (2016-12-05).
* Remove BOARDIOC_CAN_INITIALIZE. CAN initialization is now done in the
board initialization logic just like every other device driver
(2016-12-06).
* STM32F7: Allow the config to override the clock edge setting. From
David Sidrane (2016-12-06).
* For Cortex-A9, should also set ACTLR.FW in SMP mode to enble TLB and
cache broadcasts. Does not fix SMP cache problem (2016-12-07).
* sched notes: Add additional note to see if/when CPU is started in SMP
mode (2016-12-07).
* EFM32: Fix a compilation error. From Pierre-noel Bouteville
(2016-12-07).
* pthreads: Add pthread_cleanup_push() and pthread_cleanup_pop()
(2016-12-08).
* BUGFIX:STM32F427 was rebooting. Over reached family. From David
Sidrane (2016-12-08).
* Add pthread_setcanceltype() and pthread_testcancel() (2016-12-09).
* Added STM32F469 RAM size and deliberated STM32F446 size. From David
Sidrane (2016-12-09).
* Typo in stm32f76xx77xx_pinmap.h edited online with Bitbucket. From
David Sidrane (2016-12-09).
* stm32_allocateheap.c edited online with Bitbucket. From David Sidrane
(2016-12-09).
* LPC43xx SD card: Correct pin configuration options needed for SD card
pins. From Alan Carvalho de Assis (2016-12-09).
* pthread_mutex_destroy(): Fix an error in destroying a mutex which can
occur after a pthread has been canceled while holding the mutex
(2016-12-09).
* Add support for cancellation points (2016-12-09).
* Forgot to add some files in the last commit (2016-12-10).
* Correct some default font IDs. From Pierre-Noel Bouteville
(2016-12-10).
* task_delete() now obeys all cancellation point semantics (2016-12-10).
* Add task_setcancelstate(), task_setcanceltype(), and task_testcancel().
These are non-standard interfaces analogous to the correponding pthread_
interfaces that provide cancellation controls for tasks (2016-12-10).
* i.MX6 interrupt handling: Additional logic needed to handle nested
interrupts when an interrupt stack is used (2016-12-13).
* SAMV7 MCAN: Prevent Interrupt-Flooding of ACKE when not connected to
CAN-BUS. An Acknowledge-Error will occur every time no other CAN Node
acknowledges the message sent. This will also occur if the device is
not connected to the can-bus. The CAN-Standard declares, that the Chip
has to retry a given message as long as it is not sent successfully (or
it is not cancelled by the application). Every time the chip tries to
resend the message an Acknowledge-Error-Interrupt is generated. At high
baud rates this can lead in extremely high CPU load just for handling
the interrupts (and possibly the error handling in the application). To
prevent this Interrupt-Flooding we disable the ACKE once it is seen as
long we didn't transfer at least one message successfully. From Frank
Benkert (2016-12-13).
* i.MX6: Remove non-cached, inter-cpu memory region. Not a useful
concept (2016-12-13).
* minnsh Configurations: Remove minnsh configurations and support logic:
up_getc() and lowinstream. This was an interesting exercise to see
just how small you could get NuttX, but otherwise it was not useful:
(1) the NSH code violated the OS interface layer by callup up_getc and
up_putc directly, and (2) while waiting for character input, NSH would
call up_getc() which would hog all of the CPU. Not a reasonable
solution other than as a proof of concept (2016-12-13).
* Calypso Boards: Remove all Calypso board configurations (2016-12-13).
* Calypso: Remove Calypso architecture support and support for Calypso
SERCOMM driver (2016-12-13).
* ESP32 core v2: Two changes (1) flushes the UART TX buffer in the esp32
serial shutdown routine. The ROM bootloader does not flush the FIFO
before handing over to user code, so some of this output is not
currently seen when the UART is reconfigured in early stages of
startup. And changes the openocd config file's default flash voltage
from 1.8V to 3.3V. This is not necessary right now, but may save some
hard-to-debug moments down the track (3.3V-only flash running at 1.8V
often half-works and does weird things...). From Angus Gratton
(2016-12-14).
* Xtensa ESP32: Add missing ENTRY() and RET() macros in C callable
assembly language. At one time I though the that the ESP32 support the
CALL0 ABI. I was mistaken so there may be a few more like this
(2016-12-14).
* Xtensa ESP32: Fix a couple of bugs associated with handling of CPU
interrupts (2016-12-14).
* Xtensa ESP32: Fix several build-related issues associated with vector
section (2016-12-15).
* Xtensa ESP32: Fix missing CALL0 ABI condition (2016-12-15).
* Xtensa EPS32: Make sure that all C callable assembly functions includes
ENTRY prologue and RET epilogue (2016-12-15).
* Xtensa ESP32: Fix windowspill register handling + Use r6, not r2 when
passing paramters with call4 (2016-12-16).
* Xtensa ESP32: Use r6, not r2 when passing paramters with call4
(2016-12-16).
* Xtensa ESP32: Correct a logic problem the prevented dumping the IDLE
thread's stack on an assertion (2016-12-16).
* Xtensa ESP32: Fix some missing SMP logic (2016-12-16).
* Xtensa ESP32: Basically a redesign of the interrupt dispatch logic
(2016-12-16).
* Xtensa ESP32: Level 1 interrupts should return via RFE (2016-12-17).
* Xtensa ESP32: One register getting clobber on context save (2016-12-17).
* STM32 F7: Fix some STM32F7 copy paste errors. From David Sidrane
(2016-12-17).
* CDC/ACM Device Class: uart_ops_s portion of cdcacm will not be
initalized with correct functions if CONFIG_SERIAL_DMA is lit
(2016-12-17).
* Xtensa ESP32: Using wrong register to disable interrupts (2016-12-17).
* Xtensa ESP32: Fix clobbered a9 in co-processor context save/restore
(2016-12-17).
* Xtensa ESP32: Need to clone some logic for synchronous context switch.
Window spill logic in the conmon restores logic is inappropriate in
this context (2016-12-17).
* sscanf(): Add scansets to the scanf function. Enabled
CONFIG_LIBC_SCANSET option. From Aleksandr Vyhovanec (2016-12-17).
* Xtensa ESP32: Fix context save logic when called in window ABI
configuration. Add an IDLE stack. Don't depend on the mystery stack
received from the bootloader (2016-12-18).
* Xtensa ESP32: Need to spill registers to memory as the last dying
action before switching to a new thread (2016-12-18).
* ESP32 Serial: Add logic to prevent infinite loops in interrupt handler
(2016-12-18).
* Xtensa ESP32: Automatically mount /proc at start-up (2016-12-19).
* Xtensa ESP32: Corrects timer initialization and timer input frequency
(2016-12-19).
* Tiva PWM: Support PWM_PULSECOUNT feature for TI tiva. From Young.Mu
(2016-12-20).
* Xtensa ESP32: Missing prologue/epilogue macros on C callable function
(2016-12-20).
* Xtensa ESP32: Update APP CPU startup logic to match current Expressif
example code. Fix errors APP CPU startup (2016-12-20).
* fs/procfs: Fix procfs status for SMP case (2016-12-20).
* Xtensa ESP32: Clock frequency is different if running from IRAM or is
booting from FLASH. This is a booltloader issue (2016-12-20).
* Xtensa ESP32: Basic port is function in both single CPU and dual CPU
SMP configurations. There is an NSH configuration for each CPU
configuration (2016-12-21).
* STM32 F4: Merge in support for the Olimex STM32 P407 board (2016-12-21).
* Xtensa ESP32: Add an OS test to verify the port (2016-12-22).
* Xtensa ESP32: Corrects a problem with dispatching to signal handlers:
Cannot vector directly to the signal handling function as in other ABIs
under the Xtensa Window ABI. In that case, we need to go through a
tiny hook when performs the correct window call (call4) otherwise
registers will be scrambled in the signal handler (2016-12-22).
* SAMV7 CAN: Make delete_filter functions more robust. From Frank
Benkert (2016-12-23).
* Xtensa ESP32: Add stack checking logic (2016-12-23).
* sched note: record ID enumeration now results on constant values; ID
values do not change with configuration. This makes writing
post-processing software much easier (2016-12-24).
* STM32 F3: Forgot to update chip.h for STM32F303x[BC]'s 4 ADCs
(2016-12-24).
* STM32 F4: Allow dma in 1 bit mode in STM32F4xxx. From David Sidrane
(2016-12-24).
* termios.h: Fix CRTSCTS define to include input and output flow.
From Lorenz Meier (2016-12-26).
* SMP: Enforce this rule: Tasks which are normally restored when
sched_unlock() is called must remain pending (1) if we are in a
critical section, i.e., g_cpu_irqlock is locked , or (2) other CPUs
still have pre-emption disabled, i.e., g_cpu_schedlock is locked. In
those cases, the release of the pending tasks must be deferred until
those conditions are met (2016-12-26).
7.19 2016-xx-xx Gregory Nutt <gnutt@nuttx.org>
7.20 2017-xx-xx Gregory Nutt <gnutt@nuttx.org>

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: October 8, 2016</p>
<p>Last Updated: December 26, 2016</p>
</td>
</tr>
</table>
@ -317,7 +317,7 @@
<td><br></td>
<td>
<p>
<li>POSIX/ANSI-like task controls, named message queues, counting semaphores, clocks/timers, signals, pthreads, environment variables, filesystem.</li>
<li>POSIX/ANSI-like task controls, named message queues, counting semaphores, clocks/timers, signals, pthreads, cancellation points, environment variables, filesystem.</li>
</p>
</tr>
@ -1339,11 +1339,11 @@
<h2>Released Versions</h2>
<p>
In addition to the ever-changing GIT repository, there are frozen released versions of NuttX available.
The current release is NuttX 7.18.
NuttX 7.18 is the 118<sup>th</sup> release of NuttX.
It was released on October 8, 2016, and is available for download from the
The current release is NuttX 7.19.
NuttX 7.19 is the 119<sup>th</sup> release of NuttX.
It was released on December 26, 2016, and is available for download from the
<a href="https://bitbucket.org/nuttx/nuttx/downloads/">Bitbucket.org</a> website.
Note that the release consists of two tarballs: <code>nuttx-7.18.tar.gz</code> and <code>apps-7.18.tar.gz</code>.
Note that the release consists of two tarballs: <code>nuttx-7.19.tar.gz</code> and <code>apps-7.19.tar.gz</code>.
Both may be needed (see the top-level <code>nuttx/README.txt</code> file for build information).
</p>
@ -1352,7 +1352,7 @@
<ul>
<li><b>nuttx</b>.
<ul><p>
Release notes for NuttX 7.18 are available <a href="https://bitbucket.org/nuttx/nuttx/downloads/">here</a>.
Release notes for NuttX 7.19 are available <a href="https://bitbucket.org/nuttx/nuttx/downloads/">here</a>.
Release notes for all released versions on NuttX are available in the <a href="https://bitbucket.org/nuttx/nuttx/src/master/ReleaseNotes" target="_blank">Bitbucket GIT</a>.
The ChangeLog for all releases of NuttX is available in the ChangeLog file that can viewed in the <a href="https://bitbucket.org/nuttx/nuttx/src/master/ChangeLog" target="_blank">Bitbucket GIT</a>.
The ChangeLog for the current release is at the bottom of that file.
@ -1360,7 +1360,7 @@
</li></ul>
<li><b>apps</b>.
<ul><p>
Release notes for NuttX 7.18 are available <a href="https://bitbucket.org/nuttx/apps/downloads/">here</a>.
Release notes for NuttX 7.19 are available <a href="https://bitbucket.org/nuttx/apps/downloads/">here</a>.
Release notes for all released versions on NuttX are available in the <a href="https://bitbucket.org/nuttx/nuttx/src/master/ReleaseNotes" target="_blank">Bitbucket GIT</a>
The ChangeLog for the all releases of <code>apps/</code> is available in the ChangeLog file that can viewed in the <a href="https://bitbucket.org/nuttx/apps/src/master/ChangeLog.txt" target="_blank">Bitbucket GIT</a>.
The ChangeLog for the current release is at the bottom of that file.
@ -1408,7 +1408,7 @@
<li><a href="#linuxusermode">Linux/Cygwin user mode simulation</a> (1)</li>
<li>ARM
<ul>
<li><a href="#arm7tdmi">ARM7TDMI</b></a> (5)</li>
<li><a href="#arm7tdmi">ARM7TDMI</b></a> (4)</li>
<li><a href="#arm920t">ARM920T</a> (1)</li>
<li><a href="#arm926ejs">ARM926EJS</a> (4)</li>
<li><a href="#armv4">Other ARMv4</a> (1)</li>
@ -1418,7 +1418,7 @@
<li><a href="#armcortexr4">ARM Cortex-R4</a> (1)</li>
<li><a href="#armcortexm0">ARM Cortex-M0/M0+</a> (7)</li>
<li><a href="#armcortexm3">ARM Cortex-M3</a> (35)</li>
<li><a href="#armcortexm4">ARM Cortex-M4</a> (31)</li>
<li><a href="#armcortexm4">ARM Cortex-M4</a> (32)</li>
<li><a href="#armcortexm7">ARM Cortex-M7</a> (7)</li>
</ul>
<li>Atmel AVR
@ -1445,6 +1445,10 @@
<li><a href="#pic32mzmips">PIC32MZ</a> (MIPS M14K) (1)</li>
</ul>
</li>
<li>Misoc
<ul>
<li><a href="#misoclm32">LM32</a> (1)</li>
</ul>
<li>Renesas/Hitachi:
<ul>
<li><a href="#superh">Renesas/Hitachi SuperH</a> (1/2)</li>
@ -1453,6 +1457,15 @@
</li>
</td>
<td bgcolor="#e4e4e4" valign="top" width="33%">
<li><a href="#riscv">RISC-V</a> (1)
<ul>
</ul>
</li>
<li>Xtensa LX6:
<ul>
<li><a href="#esp32">ESP32</a> (1)</li>
</ul>
</li>
<li>ZiLOG
<ul>
<li><a href="#zilogz16f">ZiLOG ZNEO Z16F</a> (2)</li>
@ -1502,6 +1515,11 @@
<li><a href="#at91sama5d4">Atmel SAMA5D4</a> <small>(ARM Cortex-A5)</small></li>
</ul>
</li>
<li>Expressif
<ul>
<li><a href="#esp32">ESP32</a> <small>(Dual Xtensa LX6)</small</li>
</ul>
</li>
<li>Freescale
<ul>
<li><a href="#m68hcs12">M68HCS12</a></li>
@ -1533,13 +1551,13 @@
<li><a href="#pic32mzec">PIC32MZEC Family</a> <small>(MIPS32 M14K)</small></li>
</ul>
</li>
</td>
<td bgcolor="#e4e4e4" valign="top" width="33%">
<li>Moxa
<ul>
<li><a href="#moxart">Moxa NP51x0</a> <small>(ARMv4)</small></li>
</ul>
</li>
</td>
<td bgcolor="#e4e4e4" valign="top" width="33%">
<li>nuvoTon
<ul>
<li><a href="#nuvotonnu120">nuvoTon NUC120</a> <small>(ARM Cortex-M0)</small></li>
@ -1604,7 +1622,6 @@
<li>Texas Instruments (some formerly Luminary)
<ul>
<li><a href="#tms320c5471">TI TMS320-C5471</a> <small>(ARM7TDMI)</small></li>
<li><a href="#ticalypso">TI Calypso</a> <small>(ARM7TDMI)</small></li>
<li><a href="#titms320dm320">TI TMS320-DM320</a> <small>(ARM9E6JS)</small></li>
<li><a href="#tilms6432">TI/Stellaris LM3S6432</a> <small>(ARM Cortex-M3)</small></li>
<li><a href="#tilm3s6432s2e">TI/Stellaris LM3S6432S2E</a> <small>(ARM Cortex-M3)</small></li>
@ -1695,31 +1712,6 @@
<td><br></td>
<td><hr></td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<a name="ticalypso"><b>TI Calypso</b>.</a>
This port supports the TI &quot;Calypso&quot; MCU used in various cell phones (and, in particular,
by the <a href="http://bb.osmocom.org/trac/">Osmocom-bb project</a>).
Like the c5471, NuttX operates on the ARM7 of this dual core processor.
Board support is available for the Motorola C139, C155 and W220 phones and for the Pirelli DP-L10 phone.
</p>
<ul>
<p>
<b>STATUS:</b>
This port was contributed by Denis Carilki and includes the work of Denis Carikli, Alan Carvalho de Assis, and Stefan Richter.
Calypso support first appeared in NuttX-6.17 with LCD drivers.
Support for the Calypso keyboard was added in NuttX-6.24 by Denis Carilki.
Refer to the NuttX board README files for the <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/compal_e88/README.txt" target="_blank">Compal E88</a>, <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/compal_e99/README.txt" target="_blank">Compal E99</a> and <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/pirelli_dpl10/README.txt" target="_blank">Pirelli DP-L10</a> phones for further information.
</p>
</ul>
</td>
</tr>
<tr>
<td><br></td>
<td><hr></td>
</tr>
<tr>
<td><br></td>
<td>
@ -3160,7 +3152,7 @@ nsh>
<li>
<p>
<b>Kamami STM32 Butterfly 2</b>
Support for the <a href="https://kamami.pl/zestawy-uruchomieniowe-stm32/178507-stm32butterfly2.html">Kamami STM32 Butterfly 2</a> was contributed by Michał Łyszczek in NuttX-7/18. That port features the STMicro STM32F107VC MCU.
Support for the <a href="https://kamami.pl/zestawy-uruchomieniowe-stm32/178507-stm32butterfly2.html">Kamami STM32 Butterfly 2</a> was contributed by Michał Łyszczek in NuttX-7.18. That port features the STMicro STM32F107VC MCU.
</p>
<p>
<b>STATUS:</b>
@ -3743,11 +3735,14 @@ nsh>
<li><b>NuttX-7.3</b>
Support for the Olimex STM32 H405 board was added in NuttX-7.3.
</li>
<li>
Refer to the NuttX board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/stm3240g-eval/README.txt" target="_blank">README</a> file for further information.
<li><b>NuttX-7.19</b>
Support for the Olimex STM32 P405 board was added in NuttX-7.19.
</li>
</ul>
</p>
<p>
Refer to the STM3240G-EVAL board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/stm3240g-eval/README.txt" target="_blank">README</a> file for further information.
</p>
<p>
<b>STMicro STM32F4-Discovery</b>.
This port uses the STMicro STM32F4-Discovery board featuring the STM32F407VGT6 MCU.
@ -3817,6 +3812,11 @@ nsh>
Networking configurations were added in NuttX-7.18.
See the NuttX board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-stm32-e407/README.txt" target="_blank">README</a> file for further information about the NuttX port.
</p>
<p>
<b>Olimex STM32 P407</b>.
Support for the Olimex STM32 P407 development board appeared in NuttX-7.19.
See the NuttX board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-stm32-p407/README.txt" target="_blank">README</a> file for further information about the NuttX port.
</p>
</td>
</tr>
<tr>
@ -4332,7 +4332,7 @@ Mem: 29232 5920 23312 23312
<td><br></td>
<td>
<p>
<a name="at91sam4c"><b>Atmel SAM4C</b>.</a>
<a name="at91sam4c"><b>Atmel SAM4CM</b>.</a>
General architectural support was provided for SAM4CM family in NuttX 7.3
This was <i>architecture-only</i> support, meaning that support for the boards with these chips is available, but no support for any publicly available boards was included.
The SAM4CM port should be compatible with most of the SAM3/4 drivers (like HSMCI, DMAC, etc.) but those have not be verified on hardware as of this writing.
@ -4340,6 +4340,18 @@ Mem: 29232 5920 23312 23312
</p>
</td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<b>Atmel SAM4CMP-DB</b>.
Support for the SAM4CMP-DB board was contributed to NuttX by Masayuki Ishikawa in NuttX-7.19.
The SAM4CM is a dual-CPU part and SMP was included for the ARMv7-M and SAM3/4 families.
The SAM4CMP-DB board support includes an NSH configuration that operates in an SMP configuration.
Refer to the NuttX board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/sam4cmp-db/README.txt" target="_blank">README</a> file for further information.
</p>
</td>
</tr>
<tr>
<td><br></td>
<td><hr></td>
@ -4856,6 +4868,23 @@ Mem: 29232 5920 23312 23312
</ul>
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">
<a name="misoclm32"><b>Misoc LM32</b>.</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<b>Misoc LM32 Architectural Support</b>.
Architectural support for the Misoc LM32 was contributed by Ramtin Amin in NuttX 7.19. Driver support is basic in this initial release: Serial, Timer, and Ethernet. &quot;Board&quot; support is a available for developing with Misoc LM32 under Qemu or on your custom FPGA.
</p>
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">
@ -5222,6 +5251,53 @@ BFD_ASSERT (*plt_offset != (bfd_vma) -1);
</ul>
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">
<a name="riscv"><b>RISC-V</b>.</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<b>RISC-V Architectural Support</b>.
Basic support for the RISC-V architecture was contributed by Ken Pettit in NuttX-7.19. The initial release is <i>thin</i> but a great starting point for anyone interested in RISC-V development with NuttX.
</p>
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">
<a name="esp32"><b>ESP32 <small>(Dual Xtensa LX6)</small></b>.</a>
</td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<b>Xtensa LX6 ESP32 Architectural Support</b>.
Basic architectural support for Xtensa LX6 processors and the port for the Expressif ESP32 were added in NuttX-7.19.
The basic ESP32 port is function in both single CPU and dual CPU SMP configurations.
</p>
<p>
<b>Expressif ESP32 Core v2 Board</b>
The NuttX release includes support for Expressif ESP32 Core v2 board.
There is an NSH configuration for each CPU configuration and an OS test configuration for verificatin of the port.
</p>
<p>
<b>STATUS</b>.
ESP32 support in NuttX-7.19 is functional, but very preliminary.
There is little yet in the way of device driver support.
Outstanding issues include missing clock configuration logic, missing partition tables to support correct configuration from FLASH, and some serial driver pin configuration issues.
The configuration is usable despite these limitations.
Refer to the NuttX board <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/esp32-core/README.txt" target="_blank">README</a> file for further information.
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">

View File

@ -1008,10 +1008,6 @@ drivers/
| |-- Kconfig
| |-- Make.defs
| `-- <i>(Common sensor driver source files)</i>
|-- sercomm/
| |-- Kconfig
| |-- Make.defs
| `-- <i>(Files for the Calypso SERCOMM driver)</i>
|-- serial/
| |-- Kconfig
| |-- Make.defs
@ -1170,8 +1166,6 @@ include/
| | `-- <i>(Power management header files)</i>
| |-sensors/
| | `-- <i>(Sensor device driver header files)</i>
| |-sercomm/
| | `-- <i>(SERCOMM driver header files)</i>
| |-serial/
| | `-- <i>(Serial driver header files)</i>
| |-spi/

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX README Files</i></font></big></h1>
<p>Last Updated: December 4, 2016</p>
<p>Last Updated: December 21, 2016</p>
</td>
</tr>
</table>
@ -70,12 +70,6 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/cc3200-launchpad/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- cloudctrl/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/cloudctrl/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- compal_e86/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/compal_e86/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- compal_e88/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/compal_e88/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- compal_e99/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/compal_e99/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- demo9s12ne64/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/demo9s12ne64/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- dk-tm4c129x/
@ -183,6 +177,8 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-stm32-p107/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- olimex-stm32-p207/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-stm32-p207/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- olimex-stm32-p407/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-stm32-p407/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- olimex-strp711/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/olimex-strp711/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- open1788/
@ -199,8 +195,6 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/pic32mx7mmb/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- pic32mz-starterkit/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/pic32mz-starterkit/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- pirelli_dpl10/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/pirelli_dpl10/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- qemu-i486/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/qemu-i486/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sabre-6quad/
@ -328,8 +322,6 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/drivers/mtd/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sensors/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/drivers/sensors/README.txt" target="_blank">README.txt</a>
| |- sercomm/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/drivers/sercomm/README.txt" target="_blank">README.txt</a>
| |- syslog/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/drivers/syslog/README.txt" target="_blank">README.txt</a>
| `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/drivers/README.txt" target="_blank"><b><i>README.txt</i></b></a>

View File

@ -1287,12 +1287,6 @@ nuttx/
| | `- README.txt
| |- cloudctrl
| | `- README.txt
| |- compal_e86
| | `- README.txt
| |- compal_e88
| | `- README.txt
| |- compal_e99
| | `- README.txt
| |- demo0s12ne64/
| | `- README.txt
| |- dk-tm4c129x/
@ -1399,6 +1393,8 @@ nuttx/
| | `- README.txt
| |- olimex-stm32-p207/
| | `- README.txt
| |- olimex-stm32-p407/
| | `- README.txt
| |- olimex-strp711/
| | `- README.txt
| |- open1788/
@ -1415,8 +1411,6 @@ nuttx/
| | `- README.txt
| |- pic32mz-starterkit/
| | `- README.txt
| |- pirelli_dpl10/
| | `- README.txt
| |- qemu-i486/
| | `- README.txt
| |- sabre-6quad/
@ -1544,8 +1538,6 @@ nuttx/
| | `- README.txt
| |- sensors/
| | `- README.txt
| |- sercomm/
| | `- README.txt
| |- syslog/
| | `- README.txt
| `- README.txt

View File

@ -12294,3 +12294,794 @@ detailed bugfix information):
- apps/examples/oneshot: If the requested delay is > max_delay, then
break the delay up into several pieces.
NuttX-7.19 Release Notes
------------------------
The 119th release of NuttX, Version 7.19, was made on December 26, 2016,
and is available for download from the Bitbucket.org website. Note
that release consists of two tarballs: nuttx-7.19.tar.gz and
apps-7.19.tar.gz. These are available from:
https://bitbucket.org/nuttx/nuttx/downloads
https://bitbucket.org/nuttx/apps/downloads
Both may be needed (see the top-level nuttx/README.txt file for build
information).
Additional new features and extended functionality:
* Core OS:
- sched/semaphore, sched/phread/, libc/semaphore, libc/pthread: Add
pthread_mutexattr_get/set_protocol and non-standard
sem_get/set_protocol. These may use to enable or disable priority
inheritance on a single semaphore.
- Spinlocks: Added capability to provide architecture-specific memory
barriers.
- SMP: Add spin_trylock(). Use this in conditions where other CPUs need
to stopped but we cannot call enter_critical_section().
- sched note: Extend OS instrumentation to include some SMP events.
Also add spinlock instrumentation; In SMP configurations, add a
filter mask to log only notes from certain CPUs.
- sched note: Permit spinlock and critical section notes in in-memory
buffer iff sched_not_get() interfaces is disabled.
- sched note: Add additional note to see if/when CPU is started in SMP
mode.
- sched note: Record ID enumeration now results on constant values; ID
values do not change with configuration. This makes writing post-processing software much easier.
- boardctl: Add new boardctl() command, BOARDIOC_NX_START, to start the
NX server as a kernel thread.
- pthreads: Add pthread_cleanup_push() and pthread_cleanup_pop().
- pthreads: Added pthread_setcanceltype() and pthread_testcancel().
- pthreads: Add support for cancellation points.
- task_delete() now obeys all cancellation point semantics.
- Add task_setcancelstate(), task_setcanceltype(), and
task_testcancel(). These are non-standard interfaces analogous to the
correponding pthread_ interfaces that provide cancellation controls
for tasks.
* Graphics/Display Drivers:
- boardctl: Add new boardctl() command, BOARDIOC_NX_START, to start the
NX server as a kernel thread.
* Networking/Network Drivers:
- Network drivers: Add option to use low-priority work queue to all
Ethernet and MAC level drivers.
- Network Drivers: Adapt all Ethernet (and other MAC) drivers to work
as though CONFIG_NET_MULTIBUFFER were set. Remove all references to
CONFIG_NET_MULTIBUFFER.
- Eliminate CONFIG_NO_NOINTS. There is no longer any support for
interrupt level processing of the network stack. Lots of files changed.
* Other Common Device Drivers:
- Vishay VEML6070: Add Vishay VEML6070 driver. From Alan Carvalho de
Assis.
* ARMv7-A
- ARMv7-A/i.MX6: Add SCU register definitions. Add some controls to
enable SMP cache coherency in SMP mode. Makes no difference, however
-- cache still incoherent on i.MX6.
- ARMv7 GIC: SGIs are non-maskable but go through the same path as
other, maskable interrupts. Added logic to serialize SGI processing
when necessary.
* Atmel SAM3/4:
- SAM3/4: Add SMP support for the dual-core SAM4CM. From Masayuki
Ishikawa.
* Atmel SAM3/4 Drivers:
- Add support for the SAM5CMP-DB board. From Masayuki Ishikawa.
* Atmel SAM3/4 Boards:
- SAM4CMP-DB: Add support for the Atmel SAM4CMP-DB board running in an
SMP configuration. From Masayuki Ishikawa.
- SAM4CMP-DB: Add hooks to auto-mount the procfs file system on startup
in board bring-up logic.
* Atmel SAMV7 Drivers:
- SAMv7: Register the watchdog device at the configured device path
CONFIG_WATCHDOG_DEVPATH vs. hard-coded /dev/wdt. From Frank Benkert.
* Calypso
- Calyps: Remove all Calypso board configurations. Remove Calypso
architecture support and support for Calypso SERCOMM driver.
* Misoc LM32:
- Misoc LM32: Adds basic support for the Misoc procoessors and the LM32
in particular. From Ramtin Amin.
- Misoc LM32: Add signal handling logic. From Ramtin Amin.
- Misoc LM32: Add logic to flush/invalidate caches. From Ramtin Amin.
* Misoc LM32 Drivers:
- Misoc LM32 Serial: Add interrupting Misoc serial driver. From Ramtin
Amin.
- Misoc LM32 Timer: Add timer driver. From Ramtin Amin.
- Misoc LM32: Add Misoc Ethernet driver From Ramtin Amin.
* Misoc LM32 Boards:
- Misoc LM32 Qemu: Board support for testing Misoc LM32 with Qemu. From
Ramtin Amin.
- Misoc LM32 Qemu: Integrate network support into configs/misoc/hello.
From Ramtin Amin.
- Misoc LM32 Qemu: Remove configs/misoc/include/generated directory. I
suppose the the intent now is that this is a symbolic link? DANGER!
This means that you cannot compile this code with first generating
these files a providing a symbolic link to this location! There is a
sample directory containing generated sources. This is really only
useful for performing test builds. You really must generate the Misoc
architecture for a real-life build. From Ramtin Amin.
* NXP Freescale i.MX6 Drivers:
- i.MX6: Add an untested SPI driver taken directly from the i.MX1 port.
* NXP Freescale Kinetis:
- Kinetis: Added missing headers. Kinetis broke out SPI to
kinetis/kinetis_spi.h. Broke out DMA to use the modern Nuttx chip
inclusion - still STUBS. Add Kinetis support for ARMV7-M Common
Vector and FPU. Allow CONFIG_ARMV7M_CMNVECTOR,
CONFIG_STACK_COLORATION, CONFIG_ARCH_FPU. Fix i2c driver offset
swapped for value in kinetis_i2c_putreg. From David Sidrane.
* NXP Freescale Kinetis Drivers:
- Kinetis: Add UID Unique ID. From Neil Hancock.
* NXP Freescale Kinetis Boards:
- Freedom-K64F board: Add support for UID Unique ID. From Neil Hancock.
* NXP Freescale LPC17xx Boards:
- Olimex-LPC1766-STK: Enable procfs in NSH configuration. Automount
/proc on startup.
* NXP Freescale LPC43xx Drivers:
- LPC43xx: Add timer driver: From Alan Carvalho de Assis.
- LPC43xx GPDMA driver: The GPDMA block is basically the same as the
LPC17xx. Only the clock configuration is different and LPC43xx has
four different DMA request sources, where LPC17xx has only two. From
Alan Carvalho de Assis.
* NXP Freescale LPC43xx Boards:
- Bambino 200E: Add basic support to Micromint Bambino 200E board.
This includes contributions from Jim Wolfman. From Alan Carvalho de
Assis.
- Bambino 200E: Add support for timer driver. From Alan Carvalho de
Assis.
* RGMP:
- Remove RGMP and RGMP drivers.
* RISC-V:
- RISC-V: Add support for the RISC-V architecture and
configs/nr5m100-nexys4 board. The board support on this is pretty
thin, but it seems like maybe a good idea to get the base RISC-V stuff
in since there are people interested in it. From Ken Pettit.
* STMicro STM32 Drivers:
- STM32 F3: Implemention of the STM32 F37xx SDADC module. There are
also changes to ADC, DAC modules. SDADC has only been tested in DMA
mode and does not support external TIMER triggers. This is a work in
progress. From Marc Rechté.
- STM32 F3: Add PWM driver support for STMF37xx. The changes have been
tested successfuly for TIM4 and TIM17 (different IPs). From Marc
Rechté.
- STM32 F4: Support oversampling by 8 for the STM32 F4. From David
Sidrane.
- STM32 F4: Added Timers 2-5 and control of SAI and I2S PLLs. Added
support for stmf469 SAI and I2S PLL configuration and STM446 fixes.
From David Sidrane.
- STM32 F4: Expanded OTGFS support to stm32F469 and stm32f446. Added
missing bit definitions, Used stm32F469 and stm32f446 bit
definitions, Removed unsed header file. From David Sidrane.
- STM32 F4: Allow dma in 1 bit mode in STM32F4xxx. From David Sidrane.
- STM32 F7: Allow the config to override the clock edge setting. From
David Sidrane.
- STM32 L4: Support Complementary PWM outputs on STM32L4. From
Sebastien Lorquet.
- STM32 L4: Add implementation of dumpgpio for stm32l4, was required
for pwm debug. From Sebastien Lorquet.
* STMicro STM32 Boards:
- STM32F103 Minimum: Add button support. From Alan Carvalho de Assis.
- STM32F103 Minimum: Add support to PWM on STM32F103-Minimum board.
From Alan Carvalho de Assis.
- STM32F103 Minimum: Add RGB LED support on STM32F103 Minimum board.
From Alan Carvalho de Assis.
- STM32F103 Minimum: Add Vishay VEML6070 driver support to the
STM32F103-Minimum board. From Alan Carvalho de Assis.
- Nucleo-F303RE: Add STM32 F303RE hello configuration. From Marc
Rechté.
- Nucleo-L476: Support PWM testing on board Nucleo L476. From
Sebastien Lorquet.
- Nucleo L476: Add support for timers to Nucleo L476. From Sebastien
Lorquet.
- Hymini STM32v: Enable CONFIG_RTC in the hymini-stm32v/nsh2
(kitchensink) config. From Maciej Wójcik.
- Olimex STM32-p407: Add support for the Olimex STM32 P407 board.
* TI Tiva Drivers:
- Tiva PWM: Support PWM_PULSECOUNT feature for TI tiva. From Young.Mu.
* Xtensa/ESP32
- Xtensa ESP32: Basic architectural support for Xtensa processors and
the Expressif. ESP32 added.
- Xtensa ESP32: Add EXPERIMENTAL hooks to support lazy Xtensa
co-processor state restore in the future.
- Xtensa ESP32: Basic port is function in both single CPU and dual CPU
SMP configurations. There is an NSH configuration for each CPU
configuration. Outstanding issues include missing clock configuration
logic, missing partition tables to support correct configuration from
FLASH, and some serial driver pin configuration issues.
- Xtensa ESP32: Add stack checking logic.
* Xtensa/ESP32 Boards:
- ESP32 Core v2: Basic support for Expressif ESP32 Core v2 board
added. The initial release includes an NSH and an SMP test
configuration.
- ESP32 Core v2: Add configuration to support linking NuttX for
execution out of IRAM.
- ESP32 Core v2: Automatically mount /proc at start-up.
- ESP32 Core v2: Add an OS test to verify the port.
* C Library/Header Files:
- libc/locale: Add a dummy setlocale() function to avoid drawing the
function from newlib. Add clocale header file.
- include/locale.h: Modify locale.h to add localeconv() and lconv
structure. From Alan Carvalho de Assis.
- libc/locale: Allows c++ code to compile with or without
CONFIG_LIBC_LOCALE and will generate a link error if
CONFIG_LIBC_LOCALE is not defined and setlocale is referenced. With
CONFIG_LIBC_LOCALE defined setlocale will act as if MB string is not
supported and return "C" for POSIX. C and "". From David Sidrane.
- libc/wchar: Add wcslen, wmemchr, wmemcmp, wmemcpy wmemset, btowc,
mbrtowc, mbtowc, wcscmp, wcscoll, and wmemmove to NuttX. From Alan
Carvalho de Assis.
- libc/wctype: Add functions wcrtomb, wcslcpy, wcsxfrm, wctob, wctomb,
wctype, localeconv, strcoll, strxfrm, swctype, towlower, towupper and
wcsftime. Add wctype.h; Move lib_wctype.c to libc/wctype. From Alan
Carvalho de Assis.
- include/ctype.h : Add isblank() macro to ctype.h. From Alan Carvalho
de Assis.
- lic/stdlib: Add strtof() and strtold() as simply a copy of strtod
with types and limits changed.
- sscanf(): Use strtof() instead of strtod() if a short floating point
value was requested. The should help performance with MCUs with
32-bit FPU support with some additional code size.
- sscanf(): Add scansets to the scanf function. Enabled
CONFIG_LIBC_SCANSET option. From Aleksandr Vyhovanec.
- include/inttypes.h: Add architecture-specific inttypes.h. From Paul
A. Patience.
- C Library: Allow option to enable IP address conversions even when
the IP address family is not supported.
* Build/Configuration System:
- The Smoothie project needs to compile C++ inside config/boardname/src/
to use with High Priority Interruption, then I modified the board
configs Makefile to support it. It works fine for the first time
compilation, but if we execute "touch config/boardname/src/Pin.cxx"
and execute "make" it will not detect that Pin.cxx was modified. I
think there is some other place I should modify, but I didn't find
it. From Alan Carvalho de Assis.
* Tools:
- tools/: Add tools/showsize.sh.
* NSH: apps/nshlib:
- NSH: dd command will show statistics. From Masayuki Ishikawa.
* Applications: apps/system:
- apps/system/sched_note: Extend to include additions to instumentation
for SMP.
- apps/system/sched_note: Add support for spinlock notes.
- apps/system/sched_note: Add support for new scheduler instrumentation.
* Platforms: apps/platform:
- ESP32 Core v2: Add platform support for the ESP32 core v2 board.
- Olimex STM32-p407: Add platform support for the Olimex STM32 P407.
* Graphics: apps/graphics
- graphics/traveler/tcledit and libwld: Add an X11 Tcl/Tk tool that can
be used to edit Traveler world files.
- Graphics: Remove all NX server taks. Instead, call boardctl() to the
NX server kernel thread.
* Applications: apps/examples:
- examples/buttons: Add a new buttons example that uses the button
character driver instead of the architecture buttons directly. From
Alan Carvalho de Assis.
- examples/cctype: Add an example to verify cctype functions.
- Remove RGMP example.
- examples/ostest: Extend the pthread cancellation test to exercise
pthread_cleanup_push() (and pthread_cleanup_pop() indirectly via
pthread_cancel() and pthread_exit().
- examples/ostest: enhance pthread cancellation test some.
Works-In-Progress:
* IEEE802.14.5/6LowPAN. Hooks and framework for this effort were
introduced in NuttX-7.15. Work has continued on this effort on
forks from the main repositories, albeit with many interruptions.
The completion of this wireless feature will postponed until at
least NuttX-7.20.
Bugfixes. Only the most critical bugfixes are listed here (see the
ChangeLog for the complete list of bugfixes and for additional, more
detailed bugfix information):
* Core OS:
- sched/semaphore: Within the OS, when a thread obtains a semaphore
count it must call sem_addholder() if CONFIG_PRIORITY_INHERITANCE is
enabled. If a count is available, then sem_wait() calls
sem_addholder(), otherwise it waited for the semaphore and called
sem_addholder() when it eventually received the count. This caused a
problem when the thread calling sem_wait() was very low priority.
When it received the count, there may be higher priority threads
"hogging" the CPU that prevent the lower priority task from running
and, as a result, the sem_addholder() may be delayed indefinitely.
The fix was to have sem_post() call sem_addholder() just before
restarting the thread waiting for the semaphore count. This problem
was noted by Benix Vincent who also suggested the solution.
- Many files: Make sure that priority inheritance is not enabled for
semaphores whose primary use is signaling (vs locking of resources) by
calling sem_setprotocol().
- sched/semaphore: sem_trywait() no longer modifies the errno value
UNLESS an error occurs. This allows these functions to be used
internally without clobbering the errno value. From Freddie Chopin.
- sched/clock: Correct clock initialization. The correct range for the
month is 0-11 but is entered as 1-12 in the .config file. Add ranges
to START_YEAR, MONTH, and DAY in sched/Kconfig.
- sched/clock: Correct calculation for the case of Tickless mode with a
32-bit timer. In that case, the calculation was returning millisecond
accuracy. That is not good when the timer accuracy is < 1 msec. From
Rajan Gill.
- Work Queue: When queuing new LP work, don't signal any threads if
they are all busy. From Heesub Shin.
- Work Queue: Signal sent from work_signal() may interrupt the low
priority worker thread that is already running. For example, the
worker thread that is waiting for a semaphore could be woken up by the
signal and break any synchronization assumption as a result. It also
does not make any sense to send signal if it is already running and
busy. This change fixes it. From Heesub Shin.
- Fix DEBUGASSERT() in group_signal.c. From Masayuki Ishikawa.
- Eliminate bad boardctl() commands: Remove all references to
BOARDIOC_PWMSETUP and board_pwm_setup(). Remove all references to
BOARDIOC_ADCSETUP and board_adc_setup(). Remove
BOARDIOC_CAN_INITIALIZE. CAN initialization is now done in the board
initialization logic just like every other device driver.
- pthreads: Fix an error in pthread_mutex_destroy(). An error could
occur while destroying a mutex after a pthread has been canceled while
holding the mutex.
- task_restart: Make sure new task starts with pre-emption disabled and
not in a critical section.
- Enter/leave Critical Sections. Major redeign to
enter/leave_critical_section logic to deal with the case where
interrupts are disabled only on the local CPU. In this case, some
rather complex spinlocks must be used to maintain the critical section
accross all CPUs.
- SMP Critical Sections: Fixes for the SMP case: (1) Change order for
SMP case in enter_critical_section: (1) Disable local interrupts
BEFORE taking spinlock and (2) If SMP is enabled, if any interrupt
handler calls enter_critical_section(), it should take the spinlock.
- SMP wdogs: Wdog timers use a tasking interface that to manipulate
wdogs, and a different interface in the timer interrupt handling logic
to manage wdog expirations. In the single CPU case, this is fine.
Since the tasking level code calls enter_critical_section, interrupts
are disabled and no conflicts can occur. But that may not be the case
in the SMP case. Most architectures do not permit disabling
interrupts on other CPUs so enter_critical_section must work
differently: Locks are required to protect code. this change adds
locking (via enter_critical section) to wdog expiration logic for the
the case if the SMP configuration.
- SMP vfork(): Fix a race condition in the SMP case. Existing logic
depended on the fact that the child would not run until waitpid was
called because the child had the same priority as the parent. BUT in
the SMP case that is not true... the child may run immediately on a
different CPU.
- SMP: This change adds a new internal interfaces and fixes a problem
with three APIs in the SMP configuration. The new internal interface
is sched_cpu_pause(tcb). This function will pause a CPU if the task
associated with 'tcb' is running on that CPU. This allows a different
CPU to modify that OS data stuctures associated with the CPU. When
the other CPU is resumed, those modifications can safely take place.
The three fixes are to handle cases in the SMP configuration where one
CPU does need to make modifications to TCB and data structures on a
task that could be running running on another CPU. Those three cases
are task_delete(), task_restart(), and execution of signal handlers.
In all three cases the solutions is basically the same: (1) Call
sched_cpu_pause(tcb) to pause the CPU on which the task is running,
(2) perform the necessary operations, then (3) call up_cpu_resume() to
restart the paused CPU.
- SMP: Add logic to avoid a deadlock condition when CPU1 is hung waiting
for g_cpu_irqlock with interrupts interrupts and CPU0 is waiting for
g_cpu_paused.
- SMP: Enforce this rule: Tasks which are normally restored when
sched_unlock() is called must remain pending (1) if we are in a
critical section, i.e., g_cpu_irqlock is locked , or (2) other CPUs
still have pre-emption disabled, i.e., g_cpu_schedlock is locked. In
those cases, the release of the pending tasks must be deferred until
those conditions are met.
* File System/Block Drivers/MTD Drivers:
- AT24XX EEPROM MTD driver: Added EEPROM timeout. Fromo Aleksandr
Vyhovanec.
- fs/procfs: Fix procfs status for SMP case.
* Graphics/Graphic Drivers:
- Fonts: Correct some default font IDs. From Pierre-Noel Bouteville.
* Common Drivers:
- usbhost/enumerate: Fix possible buffer overwrite. From Janne Rosberg.
- usbhost/composite: Fix compile; missing semicolons. From Jann Rosberg.
- syslog: Fixes required for file syslog output. From Max Kriegleder.
- SPI configuration: Fix Kconfig warning. This change moves the
ARCH_HAVE_SPI options outside the check for SPI. Those options don't
depend on SPI, and Kconfig files in arch/ enable them even if SPI
isn't enabled. Source the driver's Kconfig in drivers/Kconfig only
if support for the driver is enabled prevents us from defining these
ARCH_HAVE options in the driver's Kconfig. We should probably remove
the other checks in drivers/Kconfig and check if the drivers are
enabled only in their Kconfig. From Paul A. Patience.
- drivers/timer: Remove the timer driver TIOC_SETHANDLER IOCTL call.
This calls directly from the timer driver into application code. That
is non-standard, non-portable, and cannot be supported. Instead, add
timer driver hooks to support signal notification of timer
expiration. Signal notification logic added by Sebastien Lorquet.
- All timer lower half drivers. Port Sebastien's changes to all other
implementations of the timer lower half.
- USB MSC Device: Fix length of mode6 sense reply packet. From
Wolfgang Reißnegger.
- USB Composite Host: Fix end offset in usbhost_copyinterface(). From
Janne Rosberg.
- USB CDC/ACM Host: Add CDC_SUBCLASS_ACM and CDC_PROTO_ATM to
supported class and proto. From Janne Rosberg.
- SSD1306: Fix errors in SPI mode configuration. From Gong Darcy.
- CDC/ACM Device Class: uart_ops_s portion of cdcacm will not be
initalized with correct functions if CONFIG_SERIAL_DMA is selected.
* Networking/Network Drivers:
- drivers/net/tun.c: Fix bug in TUN interface driver. From Max Nekludov.
* ARMv7-A:
- ARMv7-A SMP: Add SMP logic to signal handling.
* ARMv7-M:
- ARMv7-M: Fix double allocation of MPU region in mmu.h.
* ARMv7-R:
- ARMv7-R: Fix compilation error. This change fixes compilation errors
on MPU support for ARMv7-R. From Heesub Shin.
- ARMv7-R: fix invalid drbar handling. In ARMv7-R, [31:5] bits of DRBAR
is physical base address and other bits are reserved and SBZ. Thus,
there is no point in passing other than the base address. From Heesub
Shin.
- ARMv7-R: Remove the redundant update on SCTLR. mpu_control() is
invoking cp15_wrsctlr() around SCTLR update redundantly. From Heesub
Shin.
- ARMv7-R: add new Kconfig entries for d/i-cache. Unlike in ARMv7-A/M,
Kconfig entries for data and instruction caches are currently missing
in ARMv7-R. This change adds those missing Kconfig entries. Actual
implmenetation for those functions will be added in the subsequent
patches. From Heesub Shin.
- ARMv7-R: Add cache handling functions. This change adds functions for
enabling and disabling d/i-caches which were missing for ARMv7-R.
From Heesub Shin.
- ARMv7-R: Fix typo in mpu support. s/ARMV7M/ARMV7R/g. From Heesub Shin.
- ARMv7-R: Fix CPSR corruption after exception handling. A sporadic
hang with consequent crash was observed when booting. It seemed to be
caused by the corrupted or wrong CPSR restored on return from
exception. NuttX restores the context using code like this: msr spsr,
r1. GCC translates this to: msr spsr_fc, r1. As a result, not all
SPSR fields are updated on exception return. This should be: msr
spsr_fsxc, r1. On some evaluation boards, spsr_svc may have totally
invalid value at power-on-reset. As it is not initialized at boot, the
code above may result in the corruption of cpsr and thus unexpected
behavior. From Heesub Shin.
- ARMv7-R: Fix to restore the Thumb flag in CPSR. Thumb flag in CPSR is
not restored back when the context switch occurs while executing thumb
instruction. From Heesub Shin.
* Atmel SAM3/4 Drivers:
- SAM3/4 UDP: Add delay between setting and clearing the endpoint RESET
bit in sam_ep_resume(). We need to add a delay between setting and
clearing the endpoint reset bit in SAM_UDP_RSTEP. Without the delay
the USB controller will (may?) not reset the endpoint. If the
endpoint is not being reset, the Data Toggle (DTGLE) bit will not to
be cleared which will cause the next transaction to fail if DTGLE is
1. If that happens the host will time-out and reset the bus. Adding
this delay may also fix the USBMSC_STALL_RACEWAR in usbmsc_scsi.c,
however this has not been verified yet. From Wolfgang Reißnegger.
- SAM3/4: Remove unused 'halted' flag from UDP driver. From Wolfgang
Reißnegger.
- SAM3/4: Remove 'stalled' flag from the UDP driver. This flag is not
necessary because the state of the endpoint can be determined using
'epstate' instead. From Wolfgang Reißnegger.
* Atmel SAM3/4 Boards:
- SAM4S Xplained Pro: Configuration uses old, improper timer interface.
CONFIG_TIMER disabled in configuration. Remove obsolete timer
initialization logic.
* Atmel SAMV7 Drivers:
- SAMv7 USBDEVHS: A problem occurred with the SAMV7 USBDEVHS driver if
the USB cable is unplugged while a large amount of data is send over
an IN endpoint using DMA. If the USB cable is plugged in again after a
few seconds it is not possible to send data over this IN endpoint
again, all other endpoints work as expected. The problem occurs
because if the USB cable is unplugged while an DMA transfer is in
flight the transfer is canceled but the register SAM_USBHS_DEVDMACTRL
is left in an undefined state. The problem was fixed the problem by
resetting the register SAM_USBHS_DEVDMACTRL to a known state.
Additionally all pending interrupts are cleared. From Stefan Kolb.
- SAMV7 MCAN: Prevent Interrupt-Flooding of ACKE when not connected to
CAN-BUS. An Acknowledge-Error will occur every time no other CAN Node
acknowledges the message sent. This will also occur if the device is
not connected to the can-bus. The CAN-Standard declares, that the Chip
has to retry a given message as long as it is not sent successfully
(or it is not cancelled by the application). Every time the chip tries
to resend the message an Acknowledge-Error-Interrupt is generated. At
high baud rates this can lead in extremely high CPU load just for
handling the interrupts (and possibly the error handling in the
application). To prevent this Interrupt-Flooding we disable the ACKE
once it is seen as long we didn't transfer at least one message
successfully. From Frank Benkert.
- SAMV7 MCAN: Make delete_filter functions more robust. From Frank
Benkert.
* Atmel SAMA5 Drivers:
- SAMA5 PWM: Driver does not build when executing from SDRAM before
board frequencies are not constant. Rather, the bootloader configures
the clocking and we must derive the clocking from the MCK left by the
bootloader. This means lots more computations. This is untested on
initial change because I don't have a good PWM test setup right now.
* Misoc LM32:
- Misoc LM32: Corrects a bug that never occured in qemu on simulation or
real fpga. The error was that the r1 register was being modified out
of context switching and not restoring it. From Ramtin Amin
* NXP Freescale i.MX6:
- i.MX6 interrupt handling: Additional logic needed to handle nested
interrupts when an interrupt stack is used. Nesting can occur because
SGI interrupts are non-maskable.
* NXP Freescale LPC43xx Drivers:
- LPC43xx serial: Fix a typo in ioctl TIOCSRS485 ioctl. From Vytautas
Lukenskas.
- LPC43xx serial: Restore RS485 mode on serial port open (if RS485 is
enabled via menuconfig). From Vytautas Lukenskas.
- LPC43xx SD/MMC: Correct some definitions on SMMC control register in
lpc43_sdmmc.h. From Alan Carvalho de Assis.
- LPC43xx SD card: Correct pin configuration options needed for SD card
pins. From Alan Carvalho de Assis.
* SiLabs EFM32:
- EFM32: Fix a compilation error. From Pierre-noel Bouteville.
* STMicro STM32 Drivers:
- STM32 CHxN channels are always outputs. From Sebastien Lorquet.
- STM32 DAC: Fix shift value whenever there are is a DAC2 and, hence,
up to three interfaces. From Marc Rechté.
- STM32 F1: Add TIM8 to STM32F103V pinmap. From Maciej Wójcik.
- STM32 F1: Fix for F1 RTC Clock, tested on F103. From Maciej Wójcik.
- STM32 F3: STM32F303xB and STM32F303xC chips have 4 ADCs. From Paul
A. Patience.
- STM32 F4: A new implementation of the STM32 F4 I2C bottom half. The
common I2C as this did not handled correctly in the current
implementation (see also https://github.com/PX4/NuttX/issues/54). The
changes almost exclusively affect the ISR. From Max Kriegleder.
- STM32 F4 OTGHS Host: If STM32F446 increase number of channels to
16. From Janne Rosberg.
- STM32 F4: I think, that Size is (highest address+1 - Base address).
Base address has been removed and if address+count >= size we are
outside of the Flash. From David Sidrane.
- STM32 F4: Fix ADC compilation error when DMA isn't enabled. From Paul
A. Patience.
- STM32 F4: STM32F427 was rebooting. Over reached family. From David
Sidrane.
- STM32 F4: Added STM32F469 RAM size and deliberated STM32F446 size.
From David Sidrane.
- STM32 F4: Typo in stm32f76xxxx_pinmap.h edited online with
Bitbucket. From David Sidrane.
- STM32 F7: stm32_i2c.c Dejavu. Fixes a bug previously found in the
F4. From David Sidrane.
- STM32 F7: OTGDEV fixed typo. From David Sidrane.
- STM32 F7: Fix to SPI-Master driver. Without this the chip select
decoding feature will not work properly. From Michael Spahlinger.
- STM32 F7: STM32F7 SD/MMC driver depends on CONFIG_SDIO_DMA which is
only defined in stm32/Kconfig. Changed to CONFIG_STM32F7_SDMMC_DMA
and defined in stm32f7/Kconfig.
- STM32 F7: Fix some STM32F7 copy paste errors. From David Sidrane.
- STM32 L4: Complementary PWM outputs on STM32L4" (1) too many
parentheses when calculating max chan count and (2) channel 4 does not
have a complementary output. From Sebastien Lorquet.
- STM32 L4: Fix I2C devices RCC registers. From Sebastien Lorquet.
- STM32 L4: Enable and renaming for 32l4 UARTs 4 and 5. From Sebastien
Lorquet.
- STM32 L4: Change the way to configure quadrature encoder prescalers.
From Sebastien Lorquet.
- STM32 L4: Correct USART1/2 definitions. Use default mbed UART4
settings. From Sebastien Lorquet.
* STMicro STM32 Boards:
- STM32F103 Minimum: Fix Timers 2 to 7 clock frequencies. From Alan
Carvalho de Assis.
- Nucleo-F303RE: Remove duplicate setting from board.h. From Marc
Rechté.
- Nucleo F303RE: Various fixes to get the ADC configuration building
again after PR. Refresh all configurations.
- Nucleo L476RG: Add better selection of timer.
* TI Tiva Boards:
- DK-TM4C129x: Typo fix. From Wolfgang Reißnegger.
* Xtensa ESP32:
- ESP32 core v2: Flush the UART TX buffer in the esp32 serial shutdown
routine. The ROM bootloader does not flush the FIFO before handing
over to user code, so some of this output is not currently seen when
the UART is reconfigured in early stages of startup. From Angus
Gratton.
- Xtensa ESP32: Corrects a problem with dispatching to signal
handlers: Cannot vector directly to the signal handling function as
in other ABIs under the Xtensa Window ABI. In that case, we need to
go through a tiny hook when performs the correct window call (call4)
otherwise registers will be scrambled in the signal handler.
* Xtensa ESP32 Boards:
- ESP32 core v2: Changes the openocd config file's default flash
voltage from 1.8V to 3.3V. This is not necessary right now, but may
save some hard-to-debug moments down the track (3.3V-only flash
running at 1.8V often half-works and does weird things...). From
Angus Gratton.
* C Library/Header Files:
- libc/stdio: Fixes sscanf() %sn where strlen(data) < n. From David
Sidrane.
- libc/stdio: Include wchar.h in lib_libvsprintf.c to fix compilation
error. From Alan Carvalho de Assis.
- include/sys/time.h: timersub macro modified per recommendations of
phreakuencies.
- include/ctype.h and cxx/cctype: Implement ctype.h functions as inline
if possible. cctype can then properly select namespace.
- include/: Fix a number of header files with mismatched 'extern C {'
and '}'.
- libc/unisted: Change brings strtol() and related functions more
conformant with POSIX. Corner cases like strtol(-2147483648, NULL,
10) now pass clang -fsanitize=integer without warnings. From Juha
Niskanen.
- libc/unistd: sleep() was returning remaining nanoseconds (kind of),
instead the remaining seconds. From Eunbong Song.
- termios.h: Fix CRTSCTS define to include input and output flow. From
Lorenz Meier.
* Build/Configuration System:
- configs/*/defconfig: The buttons example was changed to archbuttons.
As a result all of the button configurations are broken and need some
renaming in the defconfig files. Noted by Frank Berkert.
- config/*/defconfgs: More fallout from name change of
apps/examples/buttons to archbuttons.
- configs: All QE encoder files. Last change made timer hard-coded to
3. Make configurable.
- configs: Remove all traces of the no-longer existent ARCHBUTTONS
example. Remove all button configurations that depended on the
obsoleted ARCHBUTTON example.
- minnsh Configurations: Remove minnsh configurations and support
logic: up_getc() and lowinstream. This was an interesting exercise
to see just how small you could get NuttX, but otherwise it was not
useful: (1) the NSH code violated the OS interface layer by callup
up_getc() and up_putc() directly, and (2) while waiting for character
input, NSH would call up_getc() which would hog all of the CPU. Not a
reasonable solution other than as a proof of concept.
* Application Build/Configuration System:
- Make.defs: Using wrong link script if native window tool used with
Cygwin.
* apps/platform:
- ESP32 Core v2 Platform: Fix some naming that prevented building the
C++ support.
* apps/nshlib:
- NSH Library: nsh_getdirpath(), use snprint instead of sprintf to
avoid possibility of buffer overrun. Noted by Chung Hwan Kim.
* apps/system:
- Remove std_readline(). This called up_getc() and up_putc() directly,
violating the POSIX OS interface.
* apps/netutils:
- FTPD: Fixed bug that didn't free ftpd ressources on exit. From Pascal
Speck.
- NTP client: Fix missing left parenthesis. From Pierre-Noel Bouteville.
- cJSON: Import patch to fix:cJSON_PrintUnformatted() behaves unexpected
if an empty array shall be printed to text. from Jerome Lang
2012-04-19. From Pierre-Noel Bouteville.
- esp8266 update cosmetic and many bug fix. From Pierre-Noel Bouteville.
- FTPD: Fix bug un ftpd file or socket may be not closed. From
Pierre-Noel Bouteville.
* apps/modbus:
- Modbus Master is missing many files and doesn't compile at all. More
details in
https://groups.yahoo.com/neo/groups/nuttx/conversations/topics/13734.
From Vytautas Lukenskas.
* apps/examples:
- The examples/qencoder app was trying to init the encoder by a direct
call into the board, cheating in a local header to declare the
normally unavailable function prototype. From Sebastien Lorquet.
- apps/examples/timer: Should detach signal handler before exiting.
- examples/qencode: The examples/qencoder app was trying to init the
encoder by a direct call into the board, cheating in a local header to
declare the normally unavailable function prototype. From Sebastien
Lorquet.
- apps/examples/archbuttons: Removed becaue it violates OS interface
principles.
- examples/adc, pwm, can: Remove all usage of BOARDIOC_ADCTEST_SETUP,
BIOARDIOC_PWMSETUP. Remove BOARDIOC_CAN_INITIALIZE. CAN
initialization is now done in the board initialization logic just like
every other device driver.
- examples/ostest: Add some delays to the pthread cancellation test.
With deferred cancellation enabled, things happen more asynchronously.

111
TODO
View File

@ -1,4 +1,4 @@
NuttX TODO List (Last updated December 3, 2016)
NuttX TODO List (Last updated December 11, 2016)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -9,7 +9,7 @@ issues related to each board port.
nuttx/:
(13) Task/Scheduler (sched/)
(12) Task/Scheduler (sched/)
(1) SMP
(1) Memory Management (mm/)
(1) Power Management (drivers/pm)
@ -22,7 +22,7 @@ nuttx/:
(12) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
(0) Other drivers (drivers/)
(11) Libraries (libc/, libm/)
(12) Libraries (libc/, libm/)
(11) File system/Generic drivers (fs/, drivers/)
(9) Graphics Subsystem (graphics/)
(2) Build system / Toolchains
@ -101,16 +101,37 @@ o Task/Scheduler (sched/)
Status: Open
Priority: Medium Low for now
Title: ISSUES WITH atexit() AND on_exit()
Title: ISSUES WITH atexit(), on_exit(), AND pthread_cleanup_pop()
Description: These functions execute with the following bad properties:
1. They run with interrupts disabled,
2. They run in supervisor mode (if applicable), and
3. They do not obey any setup of PIC or address
environments. Do they need to?
4. In the case of task_delete() and pthread_cancel(), these
callbacks will run on the thread of execution and address
context of the caller of task. That is very bad!
The fix for all of these issues it to have the callbacks
run on the caller's thread (as with signal handlers).
run on the caller's thread as is currently done with
signal handlers. Signals are delivered differently in
PROTECTED and KERNEL modes: The deliver is involes a
signal handling trampoline function in the user address
space and two signal handlers: One to call the signal
handler trampoline in user mode (SYS_signal_handler) and
on in with the signal handler trampoline to return to
supervisor mode (SYS_signal_handler_return)
The primary difference is in the location of the signal
handling trampoline:
- In PROTECTED mode, there is on a single user space blob
with a header at the beginning of the block (at a well-
known location. There is a pointer to the signal handler
trampoline function in that header.
- In the KERNEL mode, a special process signal handler
trampoline is used at a well-known location in every
process address space (ARCH_DATA_RESERVE->ar_sigtramp).
Status: Open
Priority: Medium Low. This is an important change to some less
important interfaces. For the average user, these
@ -144,20 +165,6 @@ o Task/Scheduler (sched/)
incompatibilities could show up in porting some code).
Priority: Low
Title: REMOVE TASK_DELETE
Description: Need to remove or fix task delete. This interface is non-
standard and not safe. Arbitrary deleting tasks can cause
serious problems such as memory leaks. Better to remove it
than to retain it as a latent bug.
Currently used within the OS and also part of the
implementation of pthread_cancel() and task_restart() (which
should also go for the same reasons). It is used in
NxWM::CNxConsole to terminate console tasks and also in
apps/netutils/thttpd to kill CGI tasks that timeout.
Status: Open
Priority: Low and not easily removable.
Title: RELEASE SEMAPHORES HELD BY CANCELED THREADS:
Description: Commit: fecb9040d0e54baf14b729e556a832febfe8229e: "In
case a thread is doing a blocking operation (e.g. read())
@ -491,12 +498,6 @@ o Signals (sched/signal, arch/)
o pthreads (sched/pthreads)
^^^^^^^^^^^^^^^^^
Title: CANCELLATION POINTS
Description: pthread_cancel(): Should implement cancellation points and
pthread_testcancel()
Status: Open. No changes are planned.
Priority: Low, probably not that useful
Title: PTHREAD_PRIO_PROTECT
Description: Extend pthread_mutexattr_setprotocol() support PTHREAD_PRIO_PROTECT:
@ -557,6 +558,44 @@ o pthreads (sched/pthreads)
solution. So I discarded a few hours of programming. Not a
big loss from the experience I gained."
Title: ISSUES WITH CANCELLATION POINTS
Description: According to POIX cancellation points must occur when a thread is executing
the following functions. There are some execptions as noted:
accept() mq_timedsend() NA putpmsg() sigtimedwait()
04 aio_suspend() NA msgrcv() pwrite() NA sigwait()
NA clock_nanosleep() NA msgsnd() read() sigwaitinfo()
close() NA msync() NA readv() 01 sleep()
connect() nanosleep() recv() 02 system()
-- creat() open() recvfrom() NA tcdrain()
fcntl() pause() NA recvmsg() 01 usleep()
NA fdatasync() poll() select() -- wait()
fsync() pread() sem_timedwait() waitid()
NA getmsg() NA pselect() sem_wait() waitpid()
NA getpmsg() pthread_cond_timedwait() send() write()
NA lockf() pthread_cond_wait() NA sendmsg() NA writev()
mq_receive() pthread_join() sendto()
mq_send() pthread_testcancel() 03 sigpause()
mq_timedreceive() NA putmsg() sigsuspend()
NA Not supported
-- Doesn't need instrumentation. Handled by lower level calls.
nn See note nn
NOTE 01: sleep() and usleep() are user-space functions in the C library and cannot
serve as cancellation points. They are, however, simple wrappers around nanosleep
which is a true cancellation point.
NOTE 02: system() is actually implemented in apps/ as part of NSH. It cannot be
a cancellation point either.
NOTE 03: sigpause() is a user-space function in the C library and cannot serve as
cancellation points. It is, however, a simple wrapper around sigsuspend()
which is a true cancellation point.
NOTE 04: aio_suspend() is a user-space function in the C library and cannot serve as
cancellation points. It does call around sigtimedwait() which is a true cancellation
point.
Status: Not really open. This is just the way it is.
Priority: Nothing additional is planned.
o Message Queues (sched/mqueue)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -1451,10 +1490,28 @@ o Libraries (libc/, libm/)
2016-07-30: Numerous fixes and performance improvements from
David Alessio.
Status: Open
Priority: Low for casual users but clearly high if you need care about
Status: Open
Priority: Low for casual users but clearly high if you need care about
these incorrect corner case behaviors in the math libraries.
Title: Repartition libc functionality.
Description: There are many things implemented within the kernel (for example
under sched/pthread) that probably should be migrated in the
C library where it belongs.
I would really like to see a little flavor of a micro-kernel
at the OS interface: I would like to see more primitive OS
system calls with more higher level logic in the C library.
One awkard thing is the incompatibility of KERNEL vs FLAT
builds: In the kernel build, it would be nice to move many
of the thread-specific data items out of the TCB and into
the process address environment where they belong. It is
difficult to make this compatible with the FLAT build,
however.
Status: Open
Priority: Low
o File system / Generic drivers (fs/, drivers/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -77,6 +77,8 @@ config ARCH_X86
config ARCH_XTENSA
bool "Xtensa"
select ARCH_HAVE_STACKCHECK
select ARCH_HAVE_CUSTOMOPT
---help---
Cadence® Tensilica® Xtensa® actictures.

View File

@ -158,7 +158,6 @@ arch/arm - ARM-based micro-controllers
MCU support
arch/arm/include/a1x and arch/arm/src/a1x
arch/arm/include/c5471 and arch/arm/src/c5471
arch/arm/include/calypso and arch/arm/src/calypso
arch/arm/include/dm320 and arch/arm/src/dm320
arch/arm/include/efm32 and arch/arm/src/efm32
arch/arm/include/imx1 and arch/arm/src/imx1

View File

@ -31,16 +31,6 @@ config ARCH_CHIP_C5471
---help---
TI TMS320 C5471, A180, or DA180 (ARM7TDMI)
config ARCH_CHIP_CALYPSO
bool "Calypso"
select ARCH_ARM7TDMI
select ARCH_HAVE_HEAP2
select ARCH_HAVE_LOWVECTORS
select OTHER_UART_SERIALDRIVER
select ARCH_HAVE_POWEROFF
---help---
TI Calypso-based cell phones (ARM7TDMI)
config ARCH_CHIP_DM320
bool "TMS320 DM320"
select ARCH_ARM926EJS
@ -409,7 +399,6 @@ config ARCH_CHIP
string
default "a1x" if ARCH_CHIP_A1X
default "c5471" if ARCH_CHIP_C5471
default "calypso" if ARCH_CHIP_CALYPSO
default "dm320" if ARCH_CHIP_DM320
default "efm32" if ARCH_CHIP_EFM32
default "imx1" if ARCH_CHIP_IMX1
@ -625,9 +614,6 @@ endif
if ARCH_CHIP_C5471
source arch/arm/src/c5471/Kconfig
endif
if ARCH_CHIP_CALYPSO
source arch/arm/src/calypso/Kconfig
endif
if ARCH_CHIP_DM320
source arch/arm/src/dm320/Kconfig
endif

View File

@ -36,25 +36,4 @@
#ifndef __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Not a useful feature */
#undef SMP_INTERCPU_NONCACHED
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* In SMP configurations, save spinlocks and other inter-CPU communications
* data in a non-cached memory region.
*/
# define SP_SECTION __attribute__((section(".nocache")))
#endif
#endif /* __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H */

View File

@ -1,67 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_CLOCK_H
#define __ARCH_ARM_INCLUDE_CALYPSO_CLOCK_H
#include <stdint.h>
#define CALYPSO_PLL26_52_MHZ ((2 << 8) | 0)
#define CALYPSO_PLL26_86_7_MHZ ((10 << 8) | 2)
#define CALYPSO_PLL26_87_MHZ ((3 << 8) | 0)
#define CALYPSO_PLL13_104_MHZ ((8 << 8) | 0)
enum mclk_div {
_ARM_MCLK_DIV_1 = 0,
ARM_MCLK_DIV_1 = 1,
ARM_MCLK_DIV_2 = 2,
ARM_MCLK_DIV_3 = 3,
ARM_MCLK_DIV_4 = 4,
ARM_MCLK_DIV_5 = 5,
ARM_MCLK_DIV_6 = 6,
ARM_MCLK_DIV_7 = 7,
ARM_MCLK_DIV_1_5 = 0x80 | 1,
ARM_MCLK_DIV_2_5 = 0x80 | 2,
};
void calypso_clock_set(uint8_t vtcxo_div2, uint16_t inp, enum mclk_div mclk_div);
void calypso_pll_set(uint16_t inp);
void calypso_clk_dump(void);
/* CNTL_RST */
enum calypso_rst {
RESET_DSP = (1 << 1),
RESET_EXT = (1 << 2),
RESET_WDOG = (1 << 3),
};
void calypso_reset_set(enum calypso_rst calypso_rst, int active);
int calypso_reset_get(enum calypso_rst);
enum calypso_bank {
CALYPSO_nCS0 = 0,
CALYPSO_nCS1 = 2,
CALYPSO_nCS2 = 4,
CALYPSO_nCS3 = 6,
CALYPSO_nCS7 = 8,
CALYPSO_CS4 = 0xa,
CALYPSO_nCS6 = 0xc,
};
enum calypso_mem_width {
CALYPSO_MEM_8bit = 0,
CALYPSO_MEM_16bit = 1,
CALYPSO_MEM_32bit = 2,
};
void calypso_mem_cfg(enum calypso_bank bank, uint8_t ws,
enum calypso_mem_width width, int we);
/* Enable or disable the internal bootrom mapped to 0x0000'0000 */
void calypso_bootrom(int enable);
/* Enable or disable the debug unit */
void calypso_debugunit(int enable);
/* configure the RHEA bus bridge[s] */
void calypso_rhea_cfg(uint8_t fac0, uint8_t fac1, uint8_t timeout,
uint8_t ws_h, uint8_t ws_l, uint8_t w_en0, uint8_t w_en1);
#endif /* __ARCH_ARM_INCLUDE_CALYPSO_CLOCK_H */

View File

@ -1,31 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_DEBUG_H
#define __ARCH_ARM_INCLUDE_CALYPSO_DEBUG_H
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
#ifdef DEBUG
#define dputchar(x) putchar(x)
#define dputs(x) puts(x)
#define dphex(x,y) phex(x,y)
#define printd(x, ...) printf(x, ##__VA_ARGS__)
#else
#define dputchar(x)
#define dputs(x)
#define dphex(x,y)
#define printd(x, args ...)
#endif
#endif /* __ARCH_ARM_INCLUDE_CALYPSO_DEBUG_H */

View File

@ -1,17 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_DEFINES_H
#define __ARCH_ARM_INCLUDE_CALYPSO_DEFINES_H
#define __attribute_const__ __attribute__((__const__))
/* type properties */
#define __packed __attribute__((packed))
#define __aligned(alignment) __attribute__((aligned(alignment)))
#define __unused __attribute__((unused))
/* linkage */
#define __section(name) __attribute__((section(name)))
/* force placement in zero-waitstate memory */
#define __ramtext __section(".ramtext")
#endif /* !__ARCH_ARM_INCLUDE_CALYPSO_DEFINES_H */

View File

@ -1,81 +0,0 @@
/****************************************************************************
* arch/arm/include/calypso/irq.h
* Driver for Calypso IRQ controller
*
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2011 by Stefan Richter <ichgeh@l--putt.de>
*
* This source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_IRQ_H
#error "This file should never be included directly! Use <nuttx/irq.h>"
#endif
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_IRQ_H
#define __ARCH_ARM_INCLUDE_CALYPSO_IRQ_H
#ifndef __ASSEMBLY__
enum irq_nr {
IRQ_WATCHDOG = 0,
IRQ_TIMER1 = 1,
IRQ_TIMER2 = 2,
IRQ_TSP_RX = 3,
IRQ_TPU_FRAME = 4,
IRQ_TPU_PAGE = 5,
IRQ_SIMCARD = 6,
IRQ_UART_MODEM = 7,
IRQ_KEYPAD_GPIO = 8,
IRQ_RTC_TIMER = 9,
IRQ_RTC_ALARM_I2C = 10,
IRQ_ULPD_GAUGING = 11,
IRQ_EXTERNAL = 12,
IRQ_SPI = 13,
IRQ_DMA = 14,
IRQ_API = 15,
IRQ_SIM_DETECT = 16,
IRQ_EXTERNAL_FIQ = 17,
IRQ_UART_IRDA = 18,
IRQ_ULPD_GSM_TIMER = 19,
IRQ_GEA = 20,
_NR_IRQS
};
#endif /* __ASSEMBLY__ */
/* Don't use _NR_IRQS!!! Won't work in preprocessor... */
#define NR_IRQS 21
#define IRQ_SYSTIMER IRQ_TIMER2
#endif /* __ARCH_ARM_INCLUDE_CALYPSO_IRQ_H */

View File

@ -1,28 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_MEMORY_H
#define __ARCH_ARM_INCLUDE_CALYPSO_MEMORY_H
#define __arch_getb(a) (*(volatile unsigned char *)(a))
#define __arch_getw(a) (*(volatile unsigned short *)(a))
#define __arch_getl(a) (*(volatile unsigned int *)(a))
#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v))
#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
#define __raw_writeb(v,a) __arch_putb(v,a)
#define __raw_writew(v,a) __arch_putw(v,a)
#define __raw_writel(v,a) __arch_putl(v,a)
#define __raw_readb(a) __arch_getb(a)
#define __raw_readw(a) __arch_getw(a)
#define __raw_readl(a) __arch_getl(a)
#define writeb(v,a) __arch_putb(v,a)
#define writew(v,a) __arch_putw(v,a)
#define writel(v,a) __arch_putl(v,a)
#define readb(a) __arch_getb(a)
#define readw(a) __arch_getw(a)
#define readl(a) __arch_getl(a)
#endif /* __ARCH_ARM_INCLUDE_CALYPSO_MEMORY_H */

View File

@ -1,25 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_TIMER_H
#define __ARCH_ARM_INCLUDE_CALYPSO_TIMER_H
/* Enable or Disable a timer */
void hwtimer_enable(int num, int on);
/* Configure pre-scaler and if timer is auto-reload */
void hwtimer_config(int num, uint8_t pre_scale, int auto_reload);
/* Load a timer with the given value */
void hwtimer_load(int num, uint16_t val);
/* Read the current timer value */
uint16_t hwtimer_read(int num);
/* Enable or disable the watchdog */
void wdog_enable(int on);
/* Reset cpu using watchdog */
void wdog_reset(void);
/* power up the timers */
void hwtimer_init(void);
#endif /* __ARCH_ARM_INCLUDE_CALYPSO_TIMER_H */

View File

@ -1,6 +0,0 @@
#ifndef __ARCH_ARM_INCLUDE_CALYPSO_UWIRE_H
#define __ARCH_ARM_INCLUDE_CALYPSO_UWIRE_H
void uwire_init(void);
int uwire_xfer(int cs, int bitlen, const void *dout, void *din);
#endif

View File

@ -1374,7 +1374,7 @@
# define STM32_NLCD 0 /* (0) No LCD */
# define STM32_NUSBOTG 0 /* USB FS device, but no USB OTG FS/HS */
# define STM32_NGPIO 37 /* GPIOA-F */
# define STM32_NADC 3 /* (3) 12-bit ADC1-3 */
# define STM32_NADC 4 /* (3) 12-bit ADC1-4 */
# define STM32_NDAC 2 /* (2) 12-bit DAC1-2 */
# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */
# define STM32_NCRC 1 /* (1) CRC calculation unit */
@ -1414,7 +1414,7 @@
# define STM32_NLCD 0 /* (0) No LCD */
# define STM32_NUSBOTG 0 /* USB FS device, but no USB OTG FS/HS */
# define STM32_NGPIO 52 /* GPIOA-F */
# define STM32_NADC 3 /* (3) 12-bit ADC1-3 */
# define STM32_NADC 4 /* (3) 12-bit ADC1-4 */
# define STM32_NDAC 2 /* (2) 12-bit DAC1-2 */
# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */
# define STM32_NCRC 1 /* (1) CRC calculation unit */
@ -1494,7 +1494,7 @@
# define STM32_NLCD 0 /* (0) No LCD */
# define STM32_NUSBOTG 0 /* USB FS device, but no USB OTG FS/HS */
# define STM32_NGPIO 87 /* GPIOA-F */
# define STM32_NADC 3 /* (3) 12-bit ADC1-3 */
# define STM32_NADC 4 /* (3) 12-bit ADC1-4 */
# define STM32_NDAC 2 /* (2) 12-bit DAC1-2 */
# define STM32_NCAPSENSE 0 /* (0) No capacitive sensing channels */
# define STM32_NCRC 1 /* (1) CRC calculation unit */

View File

@ -75,7 +75,7 @@
* This function must be provided via the architecture-specific logoic.
*
* Input Parameters:
* lock - The address of spinlock object.
* lock - The address of spinlock object (r0).
*
* Returned Value:
* The spinlock is always locked upon return. The value of previous value
@ -84,6 +84,8 @@
* obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked
* (meaning that we successfully obtained the lock)
*
* Modifies: r1, r2, and lr
*
****************************************************************************/
.globl up_testset
@ -98,7 +100,7 @@ up_testset:
1:
ldrexb r2, [r0] /* Test if spinlock is locked or not */
cmp r2, r1 /* Already locked? */
beq 2f /* If alrady locked, return SP_LOCKED */
beq 2f /* If already locked, return SP_LOCKED */
/* Not locked ... attempt to lock it */

View File

@ -64,6 +64,10 @@ g_fiqtmp:
.word 0 /* Saved lr */
.word 0 /* Saved spsr */
#endif
#if CONFIG_ARCH_INTERRUPTSTACK > 3 && defined(CONFIG_ARMV7A_HAVE_GICv2)
g_nestlevel:
.word 0 /* Interrupt nesting level */
#endif
/************************************************************************************
* Private Functions
@ -172,13 +176,53 @@ arm_vectorirq:
mov r0, sp /* Get r0=xcp */
#if CONFIG_ARCH_INTERRUPTSTACK > 3
#ifdef CONFIG_ARMV7A_HAVE_GICv2
/* We will switch to the interrupt stack, UNLESS we are processing a
* nested interrupt in which case we are already using the interrupt
* stack. SGI interrupts may be nested because they are non-maskable.
*/
ldr r5, .Lirqnestlevel /* r1=Points to interrupt nesting level */
ldr r1, [r5] /* Get r1= nesting level */
add r1, r1, #1 /* Increment nesting level */
str r1, [r5] /* Save r1= nesting level */
cmp r1, #1 /* r1>1 if nested */
bgt .Lintnested /* Use current SP if nested */
#endif
/* Call arm_decodeirq() on the interrupt stack */
ldr sp, .Lirqstackbase /* SP = interrupt stack base */
str r0, [sp] /* Save the user stack pointer */
mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignment */
bl arm_decodeirq /* Call the handler */
ldr sp, [r4] /* Restore the user stack pointer */
#ifdef CONFIG_ARMV7A_HAVE_GICv2
b .Lintreturn
/* Call arm_decodeirq() on whatever stack is in place */
.Lintnested:
mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignment */
bl arm_decodeirq /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */
/* Decrement the nesting level (r5 should be preserved) */
.Lintreturn:
ldr r1, [r5] /* Get r1= nesting level */
cmp r1, #0 /* A sanity check*/
subgt r1, r1, #1 /* Decrement nesting level */
strgt r1, [r5] /* Save r1= nesting level */
#endif
#else
/* Call arm_decodeirq() on the user stack */
mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignment */
bl arm_decodeirq /* Call the handler */
@ -227,6 +271,10 @@ arm_vectorirq:
#if CONFIG_ARCH_INTERRUPTSTACK > 3
.Lirqstackbase:
.word g_intstackbase
#ifdef CONFIG_ARMV7A_HAVE_GICv2
.Lirqnestlevel:
.word g_nestlevel
#endif
#endif
.size arm_vectorirq, . - arm_vectorirq
.align 5
@ -937,7 +985,7 @@ arm_vectorfiq:
.word g_fiqtmp
#if CONFIG_ARCH_INTERRUPTSTACK > 3
.Lfiqstackbase:
.word g_intstackbase
.word g_fiqstackbase
#endif
#else
@ -965,5 +1013,21 @@ g_intstackbase:
.size g_intstackbase, 4
.size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
.globl g_fiqstackalloc
.type g_fiqstackalloc, object
.globl g_fiqstackbase
.type g_fiqstackbase, object
/************************************************************************************
* Name: g_fiqstackalloc/g_fiqstackbase
************************************************************************************/
g_fiqstackalloc:
.skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
g_fiqstackbase:
.skip 4
.size g_fiqstackbase, 4
.size g_fiqstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
#endif /* CONFIG_ARCH_INTERRUPTSTACK > 3 */
.end

View File

@ -605,9 +605,6 @@
#define MMU_L2_VECTROFLAGS (PTE_TYPE_SMALL | PTE_WRITE_THROUGH | PTE_AP_R1)
#define MMU_L2_VECTORFLAGS MMU_L2_VECTRWFLAGS
#define MMU_L1_INTERCPUFLAGS (PMD_TYPE_PTE | PMD_PTE_PXN | PMD_PTE_DOM(0))
#define MMU_L2_INTERCPUFLAGS (PTE_TYPE_SMALL | PTE_DEVICE | PTE_AP_RW1)
/* Mapped section size */
#define SECTION_SHIFT (20)

View File

@ -50,22 +50,6 @@
#include "up_arch.h"
#include "up_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -46,18 +46,6 @@
#if ((defined(CONFIG_BUILD_PROTECTED) && defined(__KERNEL__)) || \
defined(CONFIG_BUILD_KERNEL)) && !defined(CONFIG_DISABLE_SIGNALS)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -1,115 +0,0 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
comment "Calypso Configuration Options"
menu "Modem UART Configuration"
config UART_MODEM_BAUD
int "Modem UART BAUD"
default 115200
config UART_MODEM_PARITY
int "Modem UART parity"
default 0
---help---
Modem UART parity. 0=None, 1=Odd, 2=Even. Default: None
config UART_MODEM_BITS
int "Modem UART number of bits"
default 8
---help---
Modem UART number of bits. Default: 8
config UART_MODEM_2STOP
int "Modem UART two stop bits"
default 0
---help---
0=1 stop bit, 1=Two stop bits. Default: 1 stop bit
config UART_MODEM_RXBUFSIZE
int "Modem UART Rx buffer size"
default 256
---help---
Modem UART Rx buffer size. Default: 256
config UART_MODEM_TXBUFSIZE
int "Modem UART Tx buffer size"
default 256
---help---
Modem UART Tx buffer size. Default: 256
config UART_MODEM_HWFLOWCONTROL
bool "Hardware flow control"
default n
---help---
Enabled Modem UART hardware flow control. Default: n
endmenu
menu "IrDA UART Configuration"
config UART_IRDA_BAUD
int "IrDA UART BAUD"
default 115200
config UART_IRDA_PARITY
int "IrDA UART parity"
default 0
---help---
IrDA UART parity. 0=None, 1=Odd, 2=Even. Default: None
config UART_IRDA_BITS
int "IrDA UART number of bits"
default 8
---help---
IrDA UART number of bits. Default: 8
config UART_IRDA_2STOP
int "IrDA UART two stop bits"
default 0
---help---
0=1 stop bit, 1=Two stop bits. Default: 1 stop bit
config UART_IRDA_RXBUFSIZE
int "IrDA UART Rx buffer size"
default 256
---help---
IrDA UART Rx buffer size. Default: 256
config UART_IRDA_TXBUFSIZE
int "IrDA UART Tx buffer size"
default 256
---help---
IrDA UART Tx buffer size. Default: 256
config UART_IRDA_HWFLOWCONTROL
bool "Hardware flow control"
default n
---help---
Enabled IrDA UART hardware flow control. Default: n
endmenu
choice
prompt "Serial Console Selection"
default SERIAL_CONSOLE_NONE
depends on DEV_CONSOLE
# See drivers/Kconfig
config USE_SERCOMM_CONSOLE
bool "SERCOMM console"
select SERCOMM_CONSOLE
config SERIAL_MODEM_CONSOLE
bool "Serial console on modem UART"
config SERIAL_IRDA_CONSOLE
bool "Serial console on IrDA UART"
config SERIAL_CONSOLE_NONE
bool "No serial console"
endchoice

View File

@ -1,71 +0,0 @@
############################################################################
# calypso/Make.defs
#
# Copyright (C) 2007, 2013-2015 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Copyright (C) 2011 Stefan Richter. All rights reserved.
# Author: Stefan Richter <ichgeh@l--putt.de>
#
# 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 Gregory Nutt 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.
#
############################################################################
HEAD_ASRC = calypso_head.S
CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_vectors.S
CMN_ASRCS += up_nommuhead.S vfork.S
CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copyfullstate.c
CMN_CSRCS += up_createstack.c up_dataabort.c up_mdelay.c up_udelay.c
CMN_CSRCS += up_doirq.c up_exit.c up_idle.c up_initialstate.c up_initialize.c
CMN_CSRCS += up_interruptcontext.c up_prefetchabort.c up_releasepending.c
CMN_CSRCS += up_releasestack.c up_reprioritizertr.c up_schedulesigaction.c
CMN_CSRCS += up_sigdeliver.c up_stackframe.c up_syscall.c up_unblocktask.c
CMN_CSRCS += up_undefinedinsn.c up_usestack.c calypso_power.c up_vfork.c
ifeq ($(CONFIG_ELF),y)
CMN_CSRCS += up_elf.c
else ifeq ($(CONFIG_MODULE),y)
CMN_CSRCS += up_elf.c
endif
ifeq ($(CONFIG_STACK_COLORATION),y)
CMN_CSRCS += up_checkstack.c
endif
CHIP_ASRCS = calypso_lowputc.S
CHIP_CSRCS = calypso_irq.c calypso_heap.c calypso_serial.c clock.c
CHIP_CSRCS += calypso_uwire.c calypso_armio.c calypso_keypad.c
ifeq ($(CONFIG_SPI),y)
CHIP_CSRCS += calypso_spi.c
endif
ifneq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += calypso_timer.c
endif

View File

@ -1,103 +0,0 @@
/****************************************************************************
* Driver for shared features of ARMIO modules
*
* Copyright (C) 2011 Stefan Richter. All rights reserved.
* Author: Stefan Richter <ichgeh@l--putt.de>
*
* 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.
*
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <arch/calypso/memory.h>
#include <arch/calypso/armio.h>
#include "up_arch.h"
/****************************************************************************
* HW access
****************************************************************************/
#define BASE_ADDR_ARMIO 0xfffe4800
#define ARMIO_REG(x) (BASE_ADDR_ARMIO + (x))
enum armio_reg {
LATCH_IN = 0x00,
LATCH_OUT = 0x02,
IO_CNTL = 0x04,
CNTL_REG = 0x06,
LOAD_TIM = 0x08,
KBR_LATCH_REG = 0x0a,
KBC_REG = 0x0c,
BUZZ_LIGHT_REG = 0x0e,
LIGHT_LEVEL = 0x10,
BUZZER_LEVEL = 0x12,
GPIO_EVENT_MODE = 0x14,
KBD_GPIO_INT = 0x16,
KBD_GPIO_MASKIT = 0x18,
GPIO_DEBOUNCING = 0x1a,
GPIO_LATCH = 0x1c,
};
#define KBD_INT (1 << 0)
#define GPIO_INT (1 << 1)
/****************************************************************************
* ARMIO interrupt handler
* forward keypad events
* forward GPIO events
****************************************************************************/
static int kbd_gpio_irq(int irq, uint32_t *regs)
{
return calypso_kbd_irq(irq, regs);
}
/****************************************************************************
* Initialize ARMIO
****************************************************************************/
void calypso_armio(void)
{
/* Enable ARMIO clock */
putreg16(1 << 5, ARMIO_REG(CNTL_REG));
/* Mask GPIO interrupt and keypad interrupt */
putreg16(KBD_INT | GPIO_INT, ARMIO_REG(KBD_GPIO_MASKIT));
/* Attach and enable the interrupt */
irq_attach(IRQ_KEYPAD_GPIO, (xcpt_t)kbd_gpio_irq);
up_enable_irq(IRQ_KEYPAD_GPIO);
}

View File

@ -1,23 +0,0 @@
/* Place a branch to the real head at the entry point */
.section .text.start
b __start
/* Exception Vectors like they are needed for the exception vector
indirection of the internal boot ROM. The following section must
be liked to appear at 0x80001c */
.section .text.exceptions
_undef_instr:
b up_vectorundefinsn
_sw_interr:
b up_vectorswi
_prefetch_abort:
b up_vectorprefetch
_data_abort:
b up_vectordata
_reserved:
b _reserved
_irq:
b up_vectorirq
_fiq:
b up_vectorfiq

View File

@ -1,357 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/calypso_irq.c
* Driver for Calypso IRQ controller
*
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2011 by Stefan Richter <ichgeh@l--putt.de>
*
* This source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* 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 <stdio.h>
#include <stdint.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <arch/calypso/memory.h>
#include <arch/calypso/clock.h>
#include "arm.h"
#include "up_internal.h"
#include "up_arch.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BASE_ADDR_IRQ 0xfffffa00
#define BASE_ADDR_IBOOT_EXC 0x0080001C
enum irq_reg
{
IT_REG1 = 0x00,
IT_REG2 = 0x02,
MASK_IT_REG1 = 0x08,
MASK_IT_REG2 = 0x0a,
IRQ_NUM = 0x10,
FIQ_NUM = 0x12,
IRQ_CTRL = 0x14,
};
#define ILR_IRQ(x) (0x20 + (x*2))
#define IRQ_REG(x) (BASE_ADDR_IRQ + (x))
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/****************************************************************************
* Public Data
****************************************************************************/
/* g_current_regs[] holds a references to the current interrupt level
* register storage structure. If is non-NULL only during interrupt
* processing. Access to g_current_regs[] must be through the macro
* CURRENT_REGS for portability.
*/
volatile uint32_t *g_current_regs[1];
extern uint32_t _exceptions;
/****************************************************************************
* Private Data
****************************************************************************/
static uint8_t default_irq_prio[] =
{
[IRQ_WATCHDOG] = 0xff,
[IRQ_TIMER1] = 0xff,
[IRQ_TIMER2] = 0xff,
[IRQ_TSP_RX] = 0,
[IRQ_TPU_FRAME] = 3,
[IRQ_TPU_PAGE] = 0xff,
[IRQ_SIMCARD] = 0xff,
[IRQ_UART_MODEM] = 8,
[IRQ_KEYPAD_GPIO] = 4,
[IRQ_RTC_TIMER] = 9,
[IRQ_RTC_ALARM_I2C] = 10,
[IRQ_ULPD_GAUGING] = 2,
[IRQ_EXTERNAL] = 12,
[IRQ_SPI] = 0xff,
[IRQ_DMA] = 0xff,
[IRQ_API] = 0xff,
[IRQ_SIM_DETECT] = 0,
[IRQ_EXTERNAL_FIQ] = 7,
[IRQ_UART_IRDA] = 2,
[IRQ_ULPD_GSM_TIMER] = 1,
[IRQ_GEA] = 0xff,
};
/****************************************************************************
* Private Functions
****************************************************************************/
static void _irq_enable(enum irq_nr nr, int enable)
{
uintptr_t reg = IRQ_REG(MASK_IT_REG1);
uint16_t val;
if (nr > 15)
{
reg = IRQ_REG(MASK_IT_REG2);
nr -= 16;
}
val = getreg16(reg);
if (enable)
{
val &= ~(1 << nr);
}
else
{
val |= (1 << nr);
}
putreg16(val, reg);
}
static void set_default_priorities(void)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(default_irq_prio); i++)
{
uint16_t val;
uint8_t prio = default_irq_prio[i];
if (prio > 31)
{
prio = 31;
}
val = getreg16(IRQ_REG(ILR_IRQ(i)));
val &= ~(0x1f << 2);
val |= prio << 2;
/* Make edge mode default. Hopefully causes less trouble */
val |= 0x02;
putreg16(val, IRQ_REG(ILR_IRQ(i)));
}
}
/* Install the exception handlers to where the ROM loader jumps */
static void calypso_exceptions_install(void)
{
uint32_t *exceptions_dst = (uint32_t *) BASE_ADDR_IBOOT_EXC;
uint32_t *exceptions_src = &_exceptions;
int i;
for (i = 0; i < 7; i++)
{
*exceptions_dst++ = *exceptions_src++;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_irqinitialize
*
* Description:
* Setup the IRQ and FIQ controllers
*
****************************************************************************/
void up_irqinitialize(void)
{
/* Prepare hardware */
calypso_exceptions_install();
CURRENT_REGS = NULL;
/* Switch to internal ROM */
calypso_bootrom(1);
/* Set default priorities */
set_default_priorities();
/* Mask all interrupts off */
putreg16(0xffff, IRQ_REG(MASK_IT_REG1));
putreg16(0xffff, IRQ_REG(MASK_IT_REG2));
/* clear all pending interrupts */
putreg16(0, IRQ_REG(IT_REG1));
putreg16(0, IRQ_REG(IT_REG2));
/* Enable interrupts globally to the ARM core */
#ifndef CONFIG_SUPPRESS_INTERRUPTS
up_irq_restore(SVC_MODE | PSR_F_BIT);
#endif
}
/****************************************************************************
* Name: up_disable_irq
*
* Description:
* Disable the IRQ specified by 'irq'
*
****************************************************************************/
void up_disable_irq(int irq)
{
if ((unsigned)irq < NR_IRQS)
{
_irq_enable(irq, 0);
}
}
/****************************************************************************
* Name: up_enable_irq
*
* Description:
* Enable the IRQ specified by 'irq'
*
****************************************************************************/
void up_enable_irq(int irq)
{
if ((unsigned)irq < NR_IRQS)
{
_irq_enable(irq, 1);
}
}
/****************************************************************************
* Name: up_prioritize_irq
*
* Description:
* Set the priority of an IRQ.
*
****************************************************************************/
#ifndef CONFIG_ARCH_IRQPRIO
int up_prioritize_irq(int nr, int prio)
{
uint16_t val;
if (prio == -1)
{
prio = default_irq_prio[nr];
}
if (prio > 31)
{
prio = 31;
}
val = prio << 2;
putreg16(val, IRQ_REG(ILR_IRQ(nr)));
return 0;
}
#endif
/****************************************************************************
* Entry point for interrupts
****************************************************************************/
void up_decodeirq(uint32_t *regs)
{
uint8_t num, tmp;
uint32_t *saved_regs;
/* XXX: What is this???
* Passed to but ignored in IRQ handlers
* Only valid meaning is apparently non-NULL == IRQ context */
saved_regs = (uint32_t *)CURRENT_REGS;
CURRENT_REGS = regs;
/* Detect & deliver the IRQ */
num = getreg8(IRQ_REG(IRQ_NUM)) & 0x1f;
irq_dispatch(num, regs);
/* Start new IRQ agreement */
tmp = getreg8(IRQ_REG(IRQ_CTRL));
tmp |= 0x01;
putreg8(tmp, IRQ_REG(IRQ_CTRL));
CURRENT_REGS = saved_regs;
}
/****************************************************************************
* Entry point for FIQs
****************************************************************************/
void calypso_fiq(void)
{
uint8_t num, tmp;
uint32_t *regs;
/* XXX: What is this???
* Passed to but ignored in IRQ handlers
* Only valid meaning is apparently non-NULL == IRQ context */
regs = (uint32_t *)CURRENT_REGS;
CURRENT_REGS = (uint32_t *)&num;
/* Detect & deliver like an IRQ but we are in FIQ context */
num = getreg8(IRQ_REG(FIQ_NUM)) & 0x1f;
irq_dispatch(num, regs);
/* Start new FIQ agreement */
tmp = getreg8(IRQ_REG(IRQ_CTRL));
tmp |= 0x02;
putreg8(tmp, IRQ_REG(IRQ_CTRL));
CURRENT_REGS = regs;
}

View File

@ -1,385 +0,0 @@
/****************************************************************************
* Driver for Calypso keypad hardware
*
* Copyright (C) 2011 Stefan Richter. All rights reserved.
* Author: Stefan Richter <ichgeh@l--putt.de>
*
* 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.
*
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/semaphore.h>
#include <nuttx/irq.h>
#include <nuttx/fs/fs.h>
#include <stdint.h>
#include <semaphore.h>
#include <errno.h>
#include <unistd.h>
#include <sched.h>
#include <arch/calypso/defines.h>
#include <arch/calypso/memory.h>
#include <arch/calypso/timer.h>
#include <arch/calypso/armio.h>
/****************************************************************************
* HW access
****************************************************************************/
#define BASE_ADDR_ARMIO 0xfffe4800
#define ARMIO_REG(x) ((void *)BASE_ADDR_ARMIO + (x))
enum armio_reg
{
LATCH_IN = 0x00,
LATCH_OUT = 0x02,
IO_CNTL = 0x04,
CNTL_REG = 0x06,
LOAD_TIM = 0x08,
KBR_LATCH_REG = 0x0a,
KBC_REG = 0x0c,
BUZZ_LIGHT_REG = 0x0e,
LIGHT_LEVEL = 0x10,
BUZZER_LEVEL = 0x12,
GPIO_EVENT_MODE = 0x14,
KBD_GPIO_INT = 0x16,
KBD_GPIO_MASKIT = 0x18,
GPIO_DEBOUNCING = 0x1a,
GPIO_LATCH = 0x1c,
};
#define KBD_INT (1 << 0)
#define GPIO_INT (1 << 1)
/****************************************************************************
* Decoder functions for matrix and power button
****************************************************************************/
static int btn_dec(uint32_t * btn_state, uint8_t col, uint8_t reg,
char *buf, size_t buflen, size_t * len)
{
uint8_t diff = (*btn_state ^ reg) & 0x1f;
while (diff)
{
uint8_t val = diff & ~(diff - 1);
uint8_t sc = val >> 1;
sc |= sc << 2;
sc += col;
sc += (sc & 0x20) ? 0x26 : 0x3f;
if (reg & val)
{
sc |= 0x20;
}
/* Check for space in buffer and dispatch */
if (*len < buflen)
{
buf[(*len)++] = sc;
}
else
{
break;
}
/* Only change diff if dispatched/buffer not full */
diff ^= val;
}
/* Store new state of the buttons (but only if they where dispatch) */
*btn_state >>= 5;
#ifdef INCLUDE_ALL_COLS
*btn_state |= (reg ^ diff) << 20;
#else
*btn_state |= (reg ^ diff) << 15;
#endif
return diff;
}
static int pwr_btn_dec(uint32_t * state, uint8_t reg, char *buf, size_t * len)
{
if (reg)
{
/* Check for pressed power button. If pressed, ignore other
* buttons since it collides with an entire row.
*/
if (~*state & 0x80000000)
{
buf[0] = 'z';
*len = 1;
*state |= 0x80000000;
}
return 1; /* break loop in caller */
}
else
{
/* Check for released power button. */
if (*state & 0x80000000)
{
buf[0] = 'Z';
*len = 1;
*state &= 0x7fffffff;
/* Don't scan others when released; might trigger
* false keystrokes otherwise
*/
return 1;
}
}
return 0; /* Continue with other columns */
}
/****************************************************************************
* Keypad: Fileops Prototypes and Structures
****************************************************************************/
typedef FAR struct file file_t;
static int keypad_open(file_t * filep);
static int keypad_close(file_t * filep);
static ssize_t keypad_read(file_t * filep, FAR char *buffer, size_t buflen);
#ifndef CONFIG_DISABLE_POLL
static int keypad_poll(file_t * filep, FAR struct pollfd *fds, bool setup);
#endif
static const struct file_operations keypad_ops =
{
keypad_open, /* open */
keypad_close, /* close */
keypad_read, /* read */
0, /* write */
0, /* seek */
0, /* ioctl */
#ifndef CONFIG_DISABLE_POLL
keypad_poll /* poll */
#endif
};
static sem_t kbdsem;
/****************************************************************************
* Keypad: Fileops
****************************************************************************/
static int keypad_open(file_t * filep)
{
register uint16_t reg;
/* Unmask keypad interrupt */
reg = readw(ARMIO_REG(KBD_GPIO_MASKIT));
writew(reg & ~KBD_INT, ARMIO_REG(KBD_GPIO_MASKIT));
return OK;
}
static int keypad_close(file_t * filep)
{
register uint16_t reg;
/* Mask keypad interrupt */
reg = readw(ARMIO_REG(KBD_GPIO_MASKIT));
writew(reg | KBD_INT, ARMIO_REG(KBD_GPIO_MASKIT));
return OK;
}
static ssize_t keypad_read(file_t * filep, FAR char *buf, size_t buflen)
{
static uint32_t btn_state = 0;
register uint16_t reg;
uint16_t col, col_mask;
size_t len = 0;
if (buf == NULL || buflen < 1)
{
/* Well... nothing to do */
return -EINVAL;
}
retry:
col = 1;
col_mask = 0x1e;
if (!btn_state)
{
/* Drive all cols low such that all buttons cause events */
writew(0, ARMIO_REG(KBC_REG));
/* No button currently pressed, use IRQ */
reg = readw(ARMIO_REG(KBD_GPIO_MASKIT));
writew(reg & ~KBD_INT, ARMIO_REG(KBD_GPIO_MASKIT));
sem_wait(&kbdsem);
}
else
{
writew(0x1f, ARMIO_REG(KBC_REG));
usleep(80000);
}
/* Scan columns */
#ifdef INCLUDE_ALL_COLS
while (col <= 6)
{
#else
while (col <= 5)
{
#endif
/* Read keypad latch and immediately set new column since
* synchronization takes about 5usec. For the 1st round, the
* interrupt has prepared this and the context switch takes
* long enough to serve as a delay.
*/
reg = readw(ARMIO_REG(KBR_LATCH_REG));
writew(col_mask, ARMIO_REG(KBC_REG));
/* Turn pressed buttons into 1s */
reg = 0x1f & ~reg;
if (col == 1)
{
/* Power/End switch */
if (pwr_btn_dec(&btn_state, reg, buf, &len))
{
break;
}
}
else
{
/* Non-power switches */
if (btn_dec(&btn_state, col, reg, buf, buflen, &len))
{
break;
}
}
/* Select next column and respective mask */
col_mask = 0x1f & ~(1 << col++);
/* We have to wait for synchronization of the inputs. The
* processing is too fast if no/few buttons are processed.
*/
usleep(5);
/* XXX: usleep seems to suffer hugh overhead. Better this!?
* If nothing else can be done, it's overhead still wastes
* time 'usefully'.
*/
/* sched_yield(); up_udelay(2); */
}
/* If we don't have anything to return, retry to avoid EOF */
if (!len)
{
goto retry;
}
return len;
}
/****************************************************************************
* Keypad interrupt handler
* mask interrupts
* prepare column drivers for scan
* posts keypad semaphore
****************************************************************************/
int calypso_kbd_irq(int irq, uint32_t * regs)
{
register uint16_t reg;
/* Mask keypad interrupt */
reg = readw(ARMIO_REG(KBD_GPIO_MASKIT));
writew(reg | KBD_INT, ARMIO_REG(KBD_GPIO_MASKIT));
/* Turn off column drivers */
writew(0x1f, ARMIO_REG(KBC_REG));
/* Let the userspace know */
sem_post(&kbdsem);
return 0;
}
/****************************************************************************
* Initialize device, add /dev/... nodes
****************************************************************************/
void up_keypad(void)
{
/* kbssem semaphore helps leaving IRQ ctx as soon as possible. This
* semaphore is used for signaling and, hence, should not have priority
* inheritance enabled.
*/
sem_init(&kbdsem, 0, 0);
sem_setprotocol(&kbdsem, SEM_PRIO_NONE);
/* Drive cols low in idle state such that all buttons cause events */
writew(0, ARMIO_REG(KBC_REG));
(void)register_driver("/dev/keypad", &keypad_ops, 0444, NULL);
}
int keypad_kbdinit(void)
{
calypso_armio();
up_keypad();
return OK;
}

View File

@ -1,50 +0,0 @@
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <nuttx/board.h>
#include <nuttx/spi/spi.h>
#include "calypso_spi.h"
/****************************************************************************
* Name: board_power_off
*
* Description:
* Power off the board.
*
* If this function returns, then it was not possible to power-off the
* board due to some other constraints.
*
* Input Parameters:
* status - Status information provided with the power off event.
*
* Returned Value:
* If this function returns, then it was not possible to power-off the
* board due to some constraints. The return value int this case is a
* board-specific reason for the failure to shutdown.
*
****************************************************************************/
#ifdef CONFIG_BOARDCTL_POWEROFF
int board_power_off(int status)
{
struct spi_dev_s *spi = calypso_spibus_initialize(0);
uint16_t tx;
SPI_SETBITS(spi, 16);
(void)SPI_HWFEATURES(spi, 0);
tx = (1 << 6) | (1 << 1);
SPI_SNDBLOCK(spi, &tx, 1);
tx = (1 << 6) | (30 << 1);
SPI_SNDBLOCK(spi, &tx, 1);
return 0;
}
#endif

View File

@ -1,968 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/calypso_serial.c
*
* Copyright (C) 2011 Stefan Richter. All rights reserved.
* Author: Stefan Richter <ichgeh@l--putt.de>
*
* based on c5471/c5471_serial.c
* Copyright (C) 2007-2009, 2013 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 <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/serial/serial.h>
#include <arch/serial.h>
#include "chip.h"
#include "up_arch.h"
#include "up_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BASE_BAUD 115200
#if defined(CONFIG_UART_IRDA_HWFLOWCONTROL) || defined(CONFIG_UART_MODEM_HWFLOWCONTROL)
# define CONFIG_UART_HWFLOWCONTROL
#endif
#if UART_FCR_OFFS == UART_EFR_OFFS
# define UART_MULTIPLEX_REGS
/* HW flow control not supported yet */
# undef CONFIG_UART_HWFLOWCONTROL
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct uart_regs_s
{
uint32_t ier;
uint32_t lcr;
uint32_t fcr;
#ifdef CONFIG_UART_HWFLOWCONTROL
uint32_t efr;
uint32_t tcr;
#endif
};
struct up_dev_s
{
unsigned int uartbase; /* Base address of UART registers */
unsigned int baud_base; /* Base baud for conversions */
unsigned int baud; /* Configured baud */
uint8_t xmit_fifo_size; /* Size of transmit FIFO */
uint8_t irq; /* IRQ associated with this UART */
uint8_t parity; /* 0=none, 1=odd, 2=even */
uint8_t bits; /* Number of bits (7 or 8) */
#ifdef CONFIG_UART_HWFLOWCONTROL
bool flowcontrol; /* true: Hardware flow control
* is enabled. */
#endif
bool stopbits2; /* true: Configure with 2
* stop bits instead of 1 */
struct uart_regs_s regs; /* Shadow copy of readonly regs */
#ifdef CONFIG_SERCOMM_CONSOLE
bool sercomm; /* Call sercomm in interrupt if true */
#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int up_setup(struct uart_dev_s *dev);
static void up_shutdown(struct uart_dev_s *dev);
static int up_attach(struct uart_dev_s *dev);
static void up_detach(struct uart_dev_s *dev);
static int up_interrupt(int irq, void *context);
static int up_ioctl(struct file *filep, int cmd, unsigned long arg);
static int up_receive(struct uart_dev_s *dev, unsigned int *status);
static void up_rxint(struct uart_dev_s *dev, bool enable);
static bool up_rxavailable(struct uart_dev_s *dev);
static void up_send(struct uart_dev_s *dev, int ch);
static void up_txint(struct uart_dev_s *dev, bool enable);
static bool up_txready(struct uart_dev_s *dev);
static bool up_txempty(struct uart_dev_s *dev);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct uart_ops_s g_uart_ops =
{
.setup = up_setup,
.shutdown = up_shutdown,
.attach = up_attach,
.detach = up_detach,
.ioctl = up_ioctl,
.receive = up_receive,
.rxint = up_rxint,
.rxavailable = up_rxavailable,
#ifdef CONFIG_SERIAL_IFLOWCONTROL
.rxflowcontrol = NULL,
#endif
.send = up_send,
.txint = up_txint,
.txready = up_txready,
.txempty = up_txempty,
};
/* I/O buffers */
static char g_irdarxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];
static char g_irdatxbuffer[CONFIG_UART_IRDA_TXBUFSIZE];
static char g_modemrxbuffer[CONFIG_UART_MODEM_RXBUFSIZE];
static char g_modemtxbuffer[CONFIG_UART_MODEM_TXBUFSIZE];
/* This describes the state of the C5471 serial IRDA port. */
static struct up_dev_s g_irdapriv =
{
.xmit_fifo_size = UART_IRDA_XMIT_FIFO_SIZE,
.baud_base = BASE_BAUD,
.uartbase = UART_IRDA_BASE,
.baud = CONFIG_UART_IRDA_BAUD,
.irq = UART_IRQ_IRDA,
.parity = CONFIG_UART_IRDA_PARITY,
.bits = CONFIG_UART_IRDA_BITS,
#ifdef CONFIG_UART_IRDA_HWFLOWCONTROL
.flowcontrol = true,
#endif
.stopbits2 = CONFIG_UART_IRDA_2STOP,
#ifdef CONFIG_SERCOMM_CONSOLE
.sercomm = false,
#endif
};
static uart_dev_t g_irdaport =
{
.recv =
{
.size = CONFIG_UART_IRDA_RXBUFSIZE,
.buffer = g_irdarxbuffer,
},
.xmit =
{
.size = CONFIG_UART_IRDA_TXBUFSIZE,
.buffer = g_irdatxbuffer,
},
.ops = &g_uart_ops,
.priv = &g_irdapriv,
};
/* This describes the state of the C5471 serial Modem port. */
static struct up_dev_s g_modempriv =
{
.xmit_fifo_size = UART_XMIT_FIFO_SIZE,
.baud_base = BASE_BAUD,
.uartbase = UART_MODEM_BASE,
.baud = CONFIG_UART_MODEM_BAUD,
.irq = UART_IRQ_MODEM,
.parity = CONFIG_UART_MODEM_PARITY,
.bits = CONFIG_UART_MODEM_BITS,
#ifdef CONFIG_UART_MODEM_HWFLOWCONTROL
.flowcontrol = true,
#endif
.stopbits2 = CONFIG_UART_MODEM_2STOP,
#ifdef CONFIG_SERCOMM_CONSOLE
.sercomm = false,
#endif
};
static uart_dev_t g_modemport =
{
.recv =
{
.size = CONFIG_UART_MODEM_RXBUFSIZE,
.buffer = g_modemrxbuffer,
},
.xmit =
{
.size = CONFIG_UART_MODEM_TXBUFSIZE,
.buffer = g_modemtxbuffer,
},
.ops = &g_uart_ops,
.priv = &g_modempriv,
};
/* Now, which one with be tty0/console and which tty1? */
#ifdef CONFIG_SERIAL_IRDA_CONSOLE
# define CONSOLE_DEV g_irdaport
# define TTYS0_DEV g_irdaport
# define TTYS1_DEV g_modemport
#else
# define CONSOLE_DEV g_modemport
# define TTYS0_DEV g_modemport
# define TTYS1_DEV g_irdaport
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: up_inserial
****************************************************************************/
static inline uint32_t up_inserial(struct up_dev_s *priv, uint32_t offset)
{
#if UART_REGISTER_BITS == 8
return getreg8(priv->uartbase + offset);
#elif UART_REGISTER_BITS == 32
return getreg32(priv->uartbase + offset);
#else
#error Unsupported number of bits set in UART_REGISTER_BITS
#endif
}
/****************************************************************************
* Name: up_serialout
****************************************************************************/
static inline void up_serialout(struct up_dev_s *priv, uint32_t offset, uint32_t value)
{
#if UART_REGISTER_BITS == 8
putreg8(value & 0xff, priv->uartbase + offset);
#elif UART_REGISTER_BITS == 32
putreg32(value, priv->uartbase + offset);
#endif
}
/****************************************************************************
* Name: up_disableuartint
****************************************************************************/
static inline void up_disableuartint(struct up_dev_s *priv, uint16_t *ier)
{
if (ier)
{
*ier = priv->regs.ier & UART_IER_INTMASK;
}
priv->regs.ier &= ~UART_IER_INTMASK;
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
/****************************************************************************
* Name: up_restoreuartint
****************************************************************************/
static inline void up_restoreuartint(struct up_dev_s *priv, uint16_t ier)
{
priv->regs.ier |= ier & (UART_IER_RECVINT | UART_IER_XMITINT);
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
/****************************************************************************
* Name: up_waittxready
****************************************************************************/
static inline void up_waittxready(struct up_dev_s *priv)
{
int tmp;
for (tmp = 1000 ; tmp > 0 ; tmp--)
{
if ((up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0)
{
break;
}
}
}
/****************************************************************************
* Name: up_disablebreaks
****************************************************************************/
static inline void up_disablebreaks(struct up_dev_s *priv)
{
priv->regs.lcr &= ~UART_LCR_BOC;
up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
}
/****************************************************************************
* Name: up_enablebreaks
****************************************************************************/
static inline void up_enablebreaks(struct up_dev_s *priv)
{
priv->regs.lcr |= UART_LCR_BOC;
up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
}
/****************************************************************************
* Name: up_setrate
****************************************************************************/
static inline void up_setrate(struct up_dev_s *priv, unsigned int rate)
{
uint32_t div_bit_rate;
switch (rate)
{
case 115200:
div_bit_rate = BAUD_115200;
break;
case 57600:
div_bit_rate = BAUD_57600;
break;
case 38400:
div_bit_rate = BAUD_38400;
break;
case 19200:
div_bit_rate = BAUD_19200;
break;
case 4800:
div_bit_rate = BAUD_4800;
break;
case 2400:
div_bit_rate = BAUD_2400;
break;
case 1200:
div_bit_rate = BAUD_1200;
break;
case 9600:
default:
div_bit_rate = BAUD_9600;
break;
}
#ifdef UART_DIV_BIT_RATE_OFFS
up_serialout(priv, UART_DIV_BIT_RATE_OFFS, div_bit_rate);
#else
up_serialout(priv, UART_DIV_LOW_OFFS, div_bit_rate);
up_serialout(priv, UART_DIV_HIGH_OFFS, div_bit_rate >> 8);
#endif
}
/****************************************************************************
* Name: up_setup
*
* Description:
* Configure the UART baud, bits, parity, fifos, etc. This
* method is called the first time that the serial port is
* opened.
*
****************************************************************************/
#include <stdio.h>
static int up_setup(struct uart_dev_s *dev)
{
#ifndef CONFIG_SUPPRESS_UART_CONFIG
struct up_dev_s *priv = dev->priv;
unsigned int cval;
if (priv->bits == 7)
{
cval = UART_LCR_7BITS;
}
else
{
cval = UART_LCR_8BITS;
}
if (priv->stopbits2)
{
cval |= UART_LCR_2STOP;
}
if (priv->parity == 1) /* Odd parity */
{
cval |= (UART_LCR_PAREN | UART_LCR_PARODD);
}
else if (priv->parity == 2) /* Even parity */
{
cval |= (UART_LCR_PAREN | UART_LCR_PAREVEN);
}
/* Both the IrDA and MODEM UARTs support RESET and UART mode. */
up_serialout(priv, UART_MDR_OFFS, MDR_RESET_MODE);
up_serialout(priv, UART_LCR_OFFS, 0xbf);
up_serialout(priv, UART_XON1_OFFS, 0x00);
up_serialout(priv, UART_XON2_OFFS, 0x00);
up_serialout(priv, UART_XOFF1_OFFS, 0x00);
up_serialout(priv, UART_XOFF2_OFFS, 0x00);
up_serialout(priv, UART_EFR_OFFS, 0x00);
up_serialout(priv, UART_LCR_OFFS, 0x00);
up_mdelay(5);
up_serialout(priv, UART_MDR_OFFS, MDR_UART_MODE);
up_mdelay(5);
priv->regs.ier = up_inserial(priv, UART_IER_OFFS);
priv->regs.lcr = up_inserial(priv, UART_LCR_OFFS);
#ifdef CONFIG_UART_HWFLOWCONTROL
if (priv->flowcontrol)
{
priv->regs.efr = up_inserial(priv, UART_EFR_OFFS);
priv->regs.tcr = up_inserial(priv, UART_TCR_OFFS);
}
#endif
up_disableuartint(priv, NULL);
#ifdef UART_MULTIPLEX_REGS
up_serialout(priv, UART_LCR_OFFS, 0x00bf);
#endif
up_serialout(priv, UART_EFR_OFFS, 0x0010); /* Unprotect enhanced control */
#ifdef UART_MULTIPLEX_REGS
priv->regs.lcr = 0x80;
up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
//up_serialout(priv, UART_MCR_OFFS, 1 << 4); /* loopback */
#endif
up_serialout(priv, UART_TFCR_OFFS, 0); /* Reset to 0 */
up_serialout(priv, UART_RFCR_OFFS, UART_FCR_RX_CLR); /* Clear RX fifo */
up_serialout(priv, UART_TFCR_OFFS, UART_FCR_TX_CLR); /* Clear TX fifo */
priv->regs.fcr = UART_FCR_FIFO_EN;
up_serialout(priv, UART_TFCR_OFFS, priv->regs.fcr); /* Enable RX/TX fifos */
up_disablebreaks(priv);
/* Set the RX and TX trigger levels to the minimum */
priv->regs.fcr = (priv->regs.fcr & 0xffffff0f) | UART_FCR_FTL;
up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr);
up_setrate(priv, priv->baud);
#ifdef UART_MULTIPLEX_REGS
up_serialout(priv, UART_SCR_OFFS, 1); /* Disable DMA */
priv->regs.lcr = (uint32_t)cval; /* Configure mode, return to THR/RHR */
#else
priv->regs.lcr &= 0xffffffe0; /* clear original field, and... */
priv->regs.lcr |= (uint32_t)cval; /* Set new bits in that field. */
#endif
up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
#ifdef CONFIG_UART_HWFLOWCONTROL
if (priv->flowcontrol)
{
/* Set the FIFO level triggers for flow control
* Halt = 48 bytes, resume = 12 bytes
*/
priv->regs.tcr = (priv->regs.tcr & 0xffffff00) | 0x0000003c;
up_serialout(priv, UART_TCR_OFFS, priv->regs.tcr);
/* Enable RTS/CTS flow control */
priv->regs.efr |= 0x000000c0;
up_serialout(priv, UART_EFR_OFFS, priv->regs.efr);
}
else
{
/* Disable RTS/CTS flow control */
priv->regs.efr &= 0xffffff3f;
up_serialout(priv, UART_EFR_OFFS, priv->regs.efr);
}
#endif
#endif
return OK;
}
/****************************************************************************
* Name: up_shutdown
*
* Description:
* Disable the UART. This method is called when the serial port is closed
*
****************************************************************************/
static void up_shutdown(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv;
up_disableuartint(priv, NULL);
}
/****************************************************************************
* Name: up_attach
*
* Description:
* Configure the UART to operation in interrupt driven mode. This method is
* called when the serial port is opened. Normally, this is just after the
* the setup() method is called, however, the serial console may operate in
* a non-interrupt driven mode during the boot phase.
*
* RX and TX interrupts are not enabled when by the attach method (unless the
* hardware supports multiple levels of interrupt enabling). The RX and TX
* interrupts are not enabled until the txint() and rxint() methods are called.
*
****************************************************************************/
static int up_attach(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
int ret;
/* Attach and enable the IRQ */
ret = irq_attach(priv->irq, up_interrupt);
if (ret == OK)
{
/* Enable the interrupt (RX and TX interrupts are still disabled
* in the UART
*/
up_enable_irq(priv->irq);
}
return ret;
}
/****************************************************************************
* Name: up_detach
*
* Description:
* Detach UART interrupts. This method is called when the serial port is
* closed normally just before the shutdown method is called. The exception is
* the serial console which is never shutdown.
*
****************************************************************************/
static void up_detach(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
up_disable_irq(priv->irq);
irq_detach(priv->irq);
}
/****************************************************************************
* Name: up_interrupt
*
* Description:
* This is the UART interrupt handler. It will be invoked
* when an interrupt received on the 'irq' It should call
* uart_transmitchars or uart_receivechar to perform the
* appropriate data transfers. The interrupt handling logic\
* must be able to map the 'irq' number into the approprite
* uart_dev_s structure in order to call these functions.
*
****************************************************************************/
static int up_interrupt(int irq, void *context)
{
struct uart_dev_s *dev = NULL;
struct up_dev_s *priv;
volatile uint32_t cause;
if (g_irdapriv.irq == irq)
{
dev = &g_irdaport;
}
else if (g_modempriv.irq == irq)
{
dev = &g_modemport;
}
else
{
PANIC();
}
priv = (struct up_dev_s *)dev->priv;
cause = up_inserial(priv, UART_ISR_OFFS) & 0x0000003f;
if ((cause & 0x0000000c) == 0x0000000c)
{
uint32_t ier_val = 0;
/* Is this an interrupt from the IrDA UART? */
if (irq == UART_IRQ_IRDA)
{
/* Save the currently enabled IrDA UART interrupts
* so that we can restore the IrDA interrupt state
* below.
*/
ier_val = up_inserial(priv, UART_IER_OFFS);
/* Then disable all IrDA UART interrupts */
up_serialout(priv, UART_IER_OFFS, 0);
}
/* Receive characters from the RX fifo */
#ifdef CONFIG_SERCOMM_CONSOLE
if (priv->sercomm)
{
sercomm_recvchars(dev);
}
else
#endif
{
uart_recvchars(dev);
}
/* read UART_RHR to clear int condition
* toss = up_inserialchar(priv,&status);
*/
/* Is this an interrupt from the IrDA UART? */
if (irq == UART_IRQ_IRDA)
{
/* Restore the IrDA UART interrupt enables */
up_serialout(priv, UART_IER_OFFS, ier_val);
}
}
else if ((cause & 0x0000000c) == 0x00000004)
{
#ifdef CONFIG_SERCOMM_CONSOLE
if (priv->sercomm)
{
sercomm_recvchars(dev);
}
else
#endif
{
uart_recvchars(dev);
}
}
if ((cause & 0x00000002) != 0)
{
#ifdef CONFIG_SERCOMM_CONSOLE
if (priv->sercomm)
{
sercomm_xmitchars(dev);
}
else
#endif
{
uart_xmitchars(dev);
}
}
return OK;
}
/****************************************************************************
* Name: up_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
{
struct inode *inode = filep->f_inode;
struct uart_dev_s *dev = inode->i_private;
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
int ret = OK;
switch (cmd)
{
#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
case TIOCSERGSTRUCT:
{
struct up_dev_s *user = (struct up_dev_s *)arg;
if (!user)
{
ret = -EINVAL;
}
else
{
memcpy(user, dev, sizeof(struct up_dev_s));
}
}
break;
#endif
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
{
irqstate_t flags = enter_critical_section();
up_enablebreaks(priv);
leave_critical_section(flags);
}
break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
{
irqstate_t flags;
flags = enter_critical_section();
up_disablebreaks(priv);
leave_critical_section(flags);
}
break;
default:
ret = -ENOTTY;
break;
}
return ret;
}
/****************************************************************************
* Name: up_receive
*
* Description:
* Called (usually) from the interrupt level to receive one character from
* the UART. Error bits associated with the receipt are provided in the
* the return 'status'.
*
****************************************************************************/
static int up_receive(struct uart_dev_s *dev, unsigned int *status)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
uint32_t rhr;
uint32_t lsr;
/* Construct a 16bit status word that uses the high byte to
* hold the status bits associated with framing,parity,break
* and a low byte that holds error bits of LSR for
* conditions such as overflow, etc.
*/
rhr = up_inserial(priv, UART_RHR_OFFS);
lsr = up_inserial(priv, UART_LSR_OFFS);
*status = (unsigned int)((rhr & 0x0000ff00) | (lsr & 0x000000ff));
return rhr & 0x000000ff;
}
/****************************************************************************
* Name: up_rxint
*
* Description:
* Call to enable or disable RX interrupts
*
****************************************************************************/
static void up_rxint(struct uart_dev_s *dev, bool enable)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->regs.ier |= UART_IER_RECVINT;
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
#endif
}
else
{
priv->regs.ier &= ~UART_IER_RECVINT;
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
}
/****************************************************************************
* Name: up_rxavailable
*
* Description:
* Return true if the receive fifo is not empty
*
****************************************************************************/
static bool up_rxavailable(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return up_inserial(priv, UART_LSR_OFFS) & UART_RX_FIFO_NOEMPTY;
}
/****************************************************************************
* Name: up_send
*
* Description:
* This method will send one byte on the UART
*
****************************************************************************/
static void up_send(struct uart_dev_s *dev, int ch)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
up_serialout(priv, UART_THR_OFFS, (uint8_t)ch);
}
/****************************************************************************
* Name: up_txint
*
* Description:
* Call to enable or disable TX interrupts
*
****************************************************************************/
static void up_txint(struct uart_dev_s *dev, bool enable)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
if (enable)
{
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
priv->regs.ier |= UART_IER_XMITINT;
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
#endif
}
else
{
priv->regs.ier &= ~UART_IER_XMITINT;
up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
}
/****************************************************************************
* Name: up_txready
*
* Description:
* Return true if the tranmsit fifo is not full
*
****************************************************************************/
static bool up_txready(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return (up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0;
}
/****************************************************************************
* Name: up_txempty
*
* Description:
* Return true if the transmit fifo is empty
*
****************************************************************************/
static bool up_txempty(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
return (up_inserial(priv, UART_LSR_OFFS) & UART_LSR_TREF) != 0;
}
/****************************************************************************
* Public Funtions
****************************************************************************/
/****************************************************************************
* Name: up_earlyserialinit
*
* Description:
* Performs the low level UART initialization early in
* debug so that the serial console will be available
* during bootup. This must be called before up_serialinit.
*
****************************************************************************/
void up_earlyserialinit(void)
{
up_disableuartint(TTYS0_DEV.priv, NULL);
up_disableuartint(TTYS1_DEV.priv, NULL);
CONSOLE_DEV.isconsole = true;
up_setup(&CONSOLE_DEV);
}
/****************************************************************************
* Name: up_serialinit
*
* Description:
* Register serial console and serial ports. This assumes
* that up_earlyserialinit was called previously.
*
****************************************************************************/
void up_serialinit(void)
{
#ifdef CONFIG_SERCOMM_CONSOLE
((struct up_dev_s *)TTYS0_DEV.priv)->sercomm = true;
(void)sercomm_register("/dev/console", &TTYS0_DEV);
(void)uart_register("/dev/ttyS0", &TTYS1_DEV);
#else
(void)uart_register("/dev/console", &CONSOLE_DEV);
(void)uart_register("/dev/ttyS0", &TTYS0_DEV);
(void)uart_register("/dev/ttyS1", &TTYS1_DEV);
#endif
}
/****************************************************************************
* Name: up_putc
*
* Description:
* Provide priority, low-level access to support OS debug
* writes
*
****************************************************************************/
int up_putc(int ch)
{
struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv;
uint16_t ier;
up_disableuartint(priv, &ier);
up_waittxready(priv);
up_serialout(priv, UART_THR_OFFS, (uint8_t)ch);
/* Check for LF */
if (ch == '\n')
{
/* Add CR */
up_waittxready(priv);
up_serialout(priv, UART_THR_OFFS, '\r');
}
up_waittxready(priv);
up_restoreuartint(priv, ier);
return ch;
}

View File

@ -1,314 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/calypso_spi.c
* SPI driver for TI Calypso
*
* Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
* Copyright (C) 2011 Stefan Richter <ichgeh@l--putt.de>
*
* Part of this source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* 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.
*
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/spi/spi.h>
#include <unistd.h>
#include <semaphore.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include "up_arch.h"
#include "calypso_spi.h"
#warning "MOST OF SPI API IS INCOMPLETE! (Wrapper around Osmocom driver)"
extern void spi_init(void);
extern int spi_xfer(uint8_t dev_idx, uint8_t bitlen, const void *dout, void *din);
#ifndef CONFIG_SPI_EXCHANGE
#error "Calypso HW only supports exchange. Enable CONFIG_SPI_EXCHANGE!"
#endif
struct calypso_spidev_s
{
struct spi_dev_s spidev; /* External driver interface */
int nbits; /* Number of transfered bits */
sem_t exclsem; /* Supports mutually exclusive access */
};
static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
{
struct calypso_spidev_s *priv = (struct calypso_spidev_s *)dev;
if (lock)
{
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&priv->exclsem) != 0)
{
/* The only case that an error should occur here is if the wait
* was awakened by a signal.
*/
DEBUGASSERT(errno == EINTR);
}
}
else
{
(void)sem_post(&priv->exclsem);
}
return OK;
}
/* STUBS! */
static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid,
bool selected)
{
}
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
{
return frequency;
}
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
{
}
/* Osmocom wrapper */
static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
{
((FAR struct calypso_spidev_s *)dev)->nbits = nbits;
}
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords)
{
FAR struct calypso_spidev_s *priv = (FAR struct calypso_spidev_s *)dev;
size_t i;
for (i = 0; i < nwords; i++)
{
spi_xfer(0, priv->nbits, txbuffer + i, rxbuffer + i);
}
}
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
{
uint16_t buf = wd;
spi_exchange(dev, &buf, &buf, 1);
return buf;
}
static const struct spi_ops_s g_spiops =
{
.lock = spi_lock,
.select = spi_select,
.setfrequency = spi_setfrequency,
.setmode = spi_setmode,
.setbits = spi_setbits,
#ifdef CONFIG_SPI_HWFEATURES
.hwfeatures = 0,
#endif
.status = 0,
#ifdef CONFIG_SPI_CMDDATA
.cmddata = 0,
#endif
.send = spi_send,
#ifdef CONFIG_SPI_EXCHANGE
.exchange = spi_exchange,
#else
.sndblock = spi_sndblock,
.recvblock = spi_recvblock,
#endif
.registercallback = 0,
};
static struct calypso_spidev_s g_spidev =
{
.spidev = { &g_spiops },
.nbits = 0,
.exclsem = SEM_INITIALIZER(1)
};
void spi_init(void)
{
putreg16(SPI_SET1_EN_CLK | SPI_SET1_WR_IRQ_DIS | SPI_SET1_RDWR_IRQ_DIS,
SPI_REG(REG_SET1));
putreg16(0x0001, SPI_REG(REG_SET2));
}
int spi_xfer(uint8_t dev_idx, uint8_t bitlen, const void *dout, void *din)
{
uint8_t bytes_per_xfer;
uint8_t reg_status, reg_ctrl = 0;
uint32_t tmp;
if (bitlen == 0)
{
return 0;
}
if (bitlen > 32)
{
return -1;
}
if (dev_idx > 4)
{
return -1;
}
bytes_per_xfer = bitlen / 8;
if (bitlen % 8)
{
bytes_per_xfer ++;
}
reg_ctrl |= (bitlen - 1) << SPI_CTRL_NB_SHIFT;
reg_ctrl |= (dev_idx & 0x7) << SPI_CTRL_AD_SHIFT;
if (bitlen <= 8)
{
tmp = *(uint8_t *)dout;
tmp <<= 24 + (8-bitlen); /* align to MSB */
}
else if (bitlen <= 16)
{
tmp = *(uint16_t *)dout;
tmp <<= 16 + (16-bitlen); /* align to MSB */
}
else
{
tmp = *(uint32_t *)dout;
tmp <<= (32-bitlen); /* align to MSB */
}
spiinfo("spi_xfer(dev_idx=%u, bitlen=%u, data_out=0x%08x): ",
dev_idx, bitlen, tmp);
/* fill transmit registers */
putreg16(tmp >> 16, SPI_REG(REG_TX_MSB));
putreg16(tmp & 0xffff, SPI_REG(REG_TX_LSB));
/* initiate transfer */
if (din)
{
reg_ctrl |= SPI_CTRL_RDWR;
}
else
{
reg_ctrl |= SPI_CTRL_WR;
}
putreg16(reg_ctrl, SPI_REG(REG_CTRL));
spiinfo("reg_ctrl=0x%04x ", reg_ctrl);
/* wait until the transfer is complete */
while (1)
{
reg_status = getreg16(SPI_REG(REG_STATUS));
spiinfo("status=0x%04x ", reg_status);
if (din && (reg_status & SPI_STATUS_RE))
{
break;
}
else if (reg_status & SPI_STATUS_WE)
{
break;
}
}
/* FIXME: calibrate how much delay we really need (seven 13MHz cycles) */
usleep(1000);
if (din)
{
tmp = getreg16(SPI_REG(REG_RX_MSB)) << 16;
tmp |= getreg16(SPI_REG(REG_RX_LSB));
spiinfo("data_in=0x%08x ", tmp);
if (bitlen <= 8)
{
*(uint8_t *)din = tmp & 0xff;
}
else if (bitlen <= 16)
{
*(uint16_t *)din = tmp & 0xffff;
}
else
{
*(uint32_t *)din = tmp;
}
}
spiinfo("\n");
return 0;
}
/****************************************************************************
* Name: calypso_spibus_initialize
*
* Description:
* Initialize the selected SPI port
*
* Input Parameter:
* Port number (for hardware that has mutiple SPI interfaces)
*
* Returned Value:
* Valid SPI device structure reference on succcess; a NULL on failure
*
****************************************************************************/
FAR struct spi_dev_s *calypso_spibus_initialize(int port)
{
switch (port)
{
case 0: /* SPI master device */
spi_init();
return (FAR struct spi_dev_s *)&g_spidev;
case 1: /* uWire device */
return NULL;
default:
return NULL;
}
}

View File

@ -1,59 +0,0 @@
#ifndef ___ARCH_ARM_SRC_CALYPSO_CALYPSO_SPI_H
#define ___ARCH_ARM_SRC_CALYPSO_CALYPSO_SPI_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BASE_ADDR_SPI 0xfffe3000
#define SPI_REG(n) (BASE_ADDR_SPI+(n))
#define SPI_SET1_EN_CLK (1 << 0)
#define SPI_SET1_WR_IRQ_DIS (1 << 4)
#define SPI_SET1_RDWR_IRQ_DIS (1 << 5)
#define SPI_CTRL_RDWR (1 << 0)
#define SPI_CTRL_WR (1 << 1)
#define SPI_CTRL_NB_SHIFT 2
#define SPI_CTRL_AD_SHIFT 7
#define SPI_STATUS_RE (1 << 0) /* Read End */
#define SPI_STATUS_WE (1 << 1) /* Write End */
/****************************************************************************
* Public Types
****************************************************************************/
enum spi_regs
{
REG_SET1 = 0x00,
REG_SET2 = 0x02,
REG_CTRL = 0x04,
REG_STATUS = 0x06,
REG_TX_LSB = 0x08,
REG_TX_MSB = 0x0a,
REG_RX_LSB = 0x0c,
REG_RX_MSB = 0x0e,
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: calypso_spibus_initialize
*
* Description:
* Initialize the selected SPI port
*
* Input Parameter:
* Port number (for hardware that has mutiple SPI interfaces)
*
* Returned Value:
* Valid SPI device structure reference on succcess; a NULL on failure
*
****************************************************************************/
FAR struct spi_dev_s *calypso_spibus_initialize(int port);
#endif /* ___ARCH_ARM_SRC_CALYPSO_CALYPSO_SPI_H */

View File

@ -1,227 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/calypso_timer.c
* Calypso DBB internal Timer Driver
*
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2011 by Stefan Richter <ichgeh@l--putt.de>
*
* This source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* 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.
*
****************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include <arch/calypso/defines.h>
#include <arch/calypso/memory.h>
#include <arch/calypso/timer.h>
#include "up_arch.h"
#define BASE_ADDR_TIMER 0xfffe3800
#define TIMER2_OFFSET 0x3000
#define TIMER_REG(n, m) (((n)-1) ? (BASE_ADDR_TIMER + TIMER2_OFFSET + (m)) : (BASE_ADDR_TIMER + (m)))
enum timer_reg
{
CNTL_TIMER = 0x00,
LOAD_TIMER = 0x02,
READ_TIMER = 0x04,
};
enum timer_ctl
{
CNTL_START = (1 << 0),
CNTL_AUTO_RELOAD = (1 << 1),
CNTL_CLOCK_ENABLE = (1 << 5),
};
/* Regular Timers (1 and 2) */
void hwtimer_enable(int num, int on)
{
uint8_t ctl;
if (num < 1 || num > 2)
{
printf("Unknown timer %d\n", num);
return;
}
ctl = getreg8(TIMER_REG(num, CNTL_TIMER));
if (on)
{
ctl |= CNTL_START | CNTL_CLOCK_ENABLE;
}
else
{
ctl &= ~CNTL_START;
}
putreg8(ctl, TIMER_REG(num, CNTL_TIMER));
}
void hwtimer_config(int num, uint8_t pre_scale, int auto_reload)
{
uint8_t ctl;
ctl = (pre_scale & 0x7) << 2;
if (auto_reload)
ctl |= CNTL_AUTO_RELOAD;
putreg8(ctl, TIMER_REG(num, CNTL_TIMER));
}
void hwtimer_load(int num, uint16_t val)
{
putreg16(val, TIMER_REG(num, LOAD_TIMER));
}
uint16_t hwtimer_read(int num)
{
uint8_t ctl = getreg8(TIMER_REG(num, CNTL_TIMER));
/* Somehow a read results in an abort */
if ((ctl & (CNTL_START | CNTL_CLOCK_ENABLE)) != (CNTL_START | CNTL_CLOCK_ENABLE))
{
return 0xffff;
}
return getreg16(TIMER_REG(num, READ_TIMER));
}
/****************************************************************************
* Watchdog Timer
****************************************************************************/
#define BASE_ADDR_WDOG 0xfffff800
#define WDOG_REG(m) (BASE_ADDR_WDOG + m)
enum wdog_reg
{
WD_CNTL_TIMER = CNTL_TIMER,
WD_LOAD_TIMER = LOAD_TIMER,
WD_READ_TIMER = 0x02,
WD_MODE = 0x04,
};
enum wdog_ctl
{
WD_CTL_START = (1 << 7),
WD_CTL_AUTO_RELOAD = (1 << 8)
};
enum wdog_mode
{
WD_MODE_DIS_ARM = 0xF5,
WD_MODE_DIS_CONFIRM = 0xA0,
WD_MODE_ENABLE = (1 << 15)
};
#define WD_CTL_PRESCALE(value) (((value)&0x07) << 9)
static void wdog_irq(__unused enum irq_nr nr)
{
puts("=> WATCHDOG\n");
}
void wdog_enable(int on)
{
if (!on)
{
putreg16(WD_MODE_DIS_ARM, WDOG_REG(WD_MODE));
putreg16(WD_MODE_DIS_CONFIRM, WDOG_REG(WD_MODE));
}
}
void wdog_reset(void)
{
/* Enable watchdog */
putreg16(WD_MODE_ENABLE, WDOG_REG(WD_MODE));
/* Force expiration */
putreg16(0x0000, WDOG_REG(WD_LOAD_TIMER));
putreg16(0x0000, WDOG_REG(WD_LOAD_TIMER));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: up_timerisr
*
* Description:
* The timer ISR will perform a variety of services for
* various portions of the systems.
*
****************************************************************************/
int up_timerisr(int irq, uint32_t *regs)
{
/* Process timer interrupt */
sched_process_timer();
return 0;
}
/****************************************************************************
* Function: up_timer_initialize
*
* Description:
* Setup Calypso HW timer 2 to cause system ticks.
*
* This function is called during start-up to initialize
* the timer interrupt.
*
****************************************************************************/
void up_timer_initialize(void)
{
up_disable_irq(IRQ_SYSTIMER);
/* The timer runs at 13MHz / 32, i.e. 406.25kHz */
/* 4062 ticks until expiry yields 100Hz interrupt */
hwtimer_load(2, 4062);
hwtimer_config(2, 0, 1);
hwtimer_enable(2, 1);
/* Attach and enable the timer interrupt */
irq_attach(IRQ_SYSTIMER, (xcpt_t)up_timerisr);
up_enable_irq(IRQ_SYSTIMER);
}

View File

@ -1,161 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/calypso_uwire.c
* Driver for Calypso uWire Master Controller
*
* (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
*
* This source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* 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 <stdint.h>
#include <stdio.h>
#include <debug.h>
#include "up_arch.h"
#define BASE_ADDR_UWIRE 0xfffe4000
#define UWIRE_REG(n) (BASE_ADDR_UWIRE+(n))
enum uwire_regs
{
REG_DATA = 0x00,
REG_CSR = 0x02,
REG_SR1 = 0x04,
REG_SR2 = 0x06,
REG_SR3 = 0x08,
};
#define UWIRE_CSR_BITS_RD(n) (((n) & 0x1f) << 0)
#define UWIRE_CSR_BITS_WR(n) (((n) & 0x1f) << 5)
#define UWIRE_CSR_IDX(n) (((n) & 3) << 10)
#define UWIRE_CSR_CS_CMD (1 << 12)
#define UWIRE_CSR_START (1 << 13)
#define UWIRE_CSR_CSRB (1 << 14)
#define UWIRE_CSR_RDRB (1 << 15)
#define UWIRE_CSn_EDGE_RD (1 << 0) /* 1=falling 0=rising */
#define UWIRE_CSn_EDGE_WR (1 << 1) /* 1=falling 0=rising */
#define UWIRE_CSn_CS_LVL (1 << 2)
#define UWIRE_CSn_FRQ_DIV2 (0 << 3)
#define UWIRE_CSn_FRQ_DIV4 (1 << 3)
#define UWIRE_CSn_FRQ_DIV8 (2 << 3)
#define UWIRE_CSn_CKH
#define UWIRE_CSn_SHIFT(n) (((n) & 1) ? 6 : 0)
#define UWIRE_CSn_REG(n) (((n) & 2) ? REG_SR2 : REG_SR1)
#define UWIRE_SR3_CLK_EN (1 << 0)
#define UWIRE_SR3_CLK_DIV2 (0 << 1)
#define UWIRE_SR3_CLK_DIV4 (1 << 1)
#define UWIRE_SR3_CLK_DIV7 (2 << 1)
#define UWIRE_SR3_CLK_DIV10 (3 << 1)
static inline void _uwire_wait(int mask, int val)
{
while ((getreg16(UWIRE_REG(REG_CSR)) & mask) != val);
}
void uwire_init(void)
{
putreg16(UWIRE_SR3_CLK_EN | UWIRE_SR3_CLK_DIV2, UWIRE_REG(REG_SR3));
/* FIXME only init CS0 for now */
putreg16(((UWIRE_CSn_CS_LVL | UWIRE_CSn_FRQ_DIV2) << UWIRE_CSn_SHIFT(0)),
UWIRE_REG(UWIRE_CSn_REG(0)));
putreg16(UWIRE_CSR_IDX(0) | UWIRE_CSR_CS_CMD, UWIRE_REG(REG_CSR));
_uwire_wait(UWIRE_CSR_CSRB, 0);
}
int uwire_xfer(int cs, int bitlen, const void *dout, void *din)
{
uint16_t tmp = 0;
if (bitlen <= 0 || bitlen > 16)
return -1;
if (cs < 0 || cs > 4)
return -1;
/* FIXME uwire_init always selects CS0 for now */
_info("uwire_xfer(dev_idx=%u, bitlen=%u\n", cs, bitlen);
/* select the chip */
putreg16(UWIRE_CSR_IDX(0) | UWIRE_CSR_CS_CMD, UWIRE_REG(REG_CSR));
_uwire_wait(UWIRE_CSR_CSRB, 0);
if (dout)
{
if (bitlen <= 8)
tmp = *(uint8_t *)dout;
else if (bitlen <= 16)
tmp = *(uint16_t *)dout;
tmp <<= 16 - bitlen; /* align to MSB */
putreg16(tmp, UWIRE_REG(REG_DATA));
_info(", data_out=0x%04hx", tmp);
}
tmp = (dout ? UWIRE_CSR_BITS_WR(bitlen) : 0) |
(din ? UWIRE_CSR_BITS_RD(bitlen) : 0) |
UWIRE_CSR_START;
putreg16(tmp, UWIRE_REG(REG_CSR));
_uwire_wait(UWIRE_CSR_CSRB, 0);
if (din)
{
_uwire_wait(UWIRE_CSR_RDRB, UWIRE_CSR_RDRB);
tmp = getreg16(UWIRE_REG(REG_DATA));
_info(", data_in=0x%08x", tmp);
if (bitlen <= 8)
*(uint8_t *)din = tmp & 0xff;
else if (bitlen <= 16)
*(uint16_t *)din = tmp & 0xffff;
}
/* unselect the chip */
putreg16(UWIRE_CSR_IDX(0) | 0, UWIRE_REG(REG_CSR));
_uwire_wait(UWIRE_CSR_CSRB, 0);
_info(")\n");
return 0;
}

View File

@ -1,211 +0,0 @@
/****************************************************************************
* calypso/chip.h
*
* Copyright (C) 2011 Stefan Richter. All rights reserved.
* Author: Stefan Richter <ichgeh@l--putt.de>
*
* based on: c5471/chip.h
* Copyright (C) 2007 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 Gregory Nutt nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_CALYPSO_CHIP_H
#define __ARCH_ARM_SRC_CALYPSO_CHIP_H
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* UARTs ********************************************************************/
#define UART_IRDA_BASE 0xffff5000
#define UART_MODEM_BASE 0xffff5800
#define UART_UIR 0xffff6000
#define UARTn_IO_RANGE 0x00000800
/* Common UART Registers. Expressed as offsets from the BASE address */
#define UART_RHR_OFFS 0x00000000 /* Rcv Holding Register */
#define UART_THR_OFFS 0x00000000 /* Xmit Holding Register */
#define UART_FCR_OFFS 0x00000002 /* FIFO Control Register */
#define UART_RFCR_OFFS 0x00000002 /* Rcv FIFO Control Register */
#define UART_TFCR_OFFS 0x00000002 /* Xmit FIFO Control Register */
#define UART_SCR_OFFS 0x00000010 /* Status Control Register */
#define UART_LCR_OFFS 0x00000003 /* Line Control Register */
#define UART_LSR_OFFS 0x00000005 /* Line Status Register */
#define UART_SSR_OFFS 0x00000011 /* Supplementary Status Register */
#define UART_MCR_OFFS 0x00000004 /* Modem Control Register */
#define UART_MSR_OFFS 0x00000006 /* Modem Status Register */
#define UART_IER_OFFS 0x00000001 /* Interrupt Enable Register */
#define UART_ISR_OFFS 0x00000002 /* Interrupt Status Register */
#define UART_EFR_OFFS 0x00000002 /* Enhanced Feature Register */
#define UART_XON1_OFFS 0x00000004 /* XON1 Character Register */
#define UART_XON2_OFFS 0x00000005 /* XON2 Character Register */
#define UART_XOFF1_OFFS 0x00000006 /* XOFF1 Character Register */
#define UART_XOFF2_OFFS 0x00000007 /* XOFF2 Character Register */
#define UART_SPR_OFFS 0x00000007 /* Scratch-pad Register */
#define UART_DIV_LOW_OFFS 0x00000000 /* Divisor for baud generation */
#define UART_DIV_HIGH_OFFS 0x00000001
#define UART_TCR_OFFS 0x00000006 /* Transmission Control Register */
#define UART_TLR_OFFS 0x00000007 /* Trigger Level Register */
#define UART_MDR_OFFS 0x00000008 /* Mode Definition Register */
/* UART Settings ************************************************************/
/* Miscellaneous UART settings. */
#define UART_REGISTER_BITS 8
#define UART_IRQ_MODEM IRQ_UART_MODEM
#define UART_IRQ_IRDA IRQ_UART_IRDA
#define UART_RX_FIFO_NOEMPTY 0x00000001
#define UART_SSR_TXFULL 0x00000001
#define UART_LSR_TREF 0x00000020
#define UART_XMIT_FIFO_SIZE 64
#define UART_IRDA_XMIT_FIFO_SIZE 64
/* UART_LCR Register */
/* Bits 31-7: Reserved */
#define UART_LCR_BOC 0x00000040 /* Bit 6: Break Control */
/* Bit 5: Parity Type 2 */
#define UART_LCR_PAREVEN 0x00000010 /* Bit 4: Parity Type 1 */
#define UART_LCR_PARODD 0x00000000
#define UART_LCR_PARMARK 0x00000010
#define UART_LCR_PARSPACE 0x00000011
#define UART_LCR_PAREN 0x00000008 /* Bit 3: Paity Enable */
#define UART_LCR_PARDIS 0x00000000
#define UART_LCR_2STOP 0x00000004 /* Bit 2: Number of stop bits */
#define UART_LCR_1STOP 0x00000000
#define UART_LCR_5BITS 0x00000000 /* Bits 0-1: Word-length */
#define UART_LCR_6BITS 0x00000001
#define UART_LCR_7BITS 0x00000002
#define UART_LCR_8BITS 0x00000003
#define UART_FCR_FTL 0x000000f0
#define UART_FCR_FIFO_EN 0x00000001
#define UART_FCR_TX_CLR 0x00000002
#define UART_FCR_RX_CLR 0x00000004
#define UART_IER_RECVINT 0x00000001
#define UART_IER_XMITINT 0x00000002
#define UART_IER_LINESTSINT 0x00000004
#define UART_IER_MODEMSTSINT 0x00000008 /* IrDA UART only */
#define UART_IER_XOFFINT 0x00000020
#define UART_IER_RTSINT 0x00000040 /* IrDA UART only */
#define UART_IER_CTSINT 0x00000080 /* IrDA UART only */
#define UART_IER_INTMASK 0x000000ff
#define BAUD_115200 0x00000007
#define BAUD_57600 0x00000014
#define BAUD_38400 0x00000021
#define BAUD_19200 0x00000006
#define BAUD_9600 0x0000000C
#define BAUD_4800 0x00000018
#define BAUD_2400 0x00000030
#define BAUD_1200 0x00000060
#define MDR_UART_MODE 0x00000000 /* Both IrDA and Modem UARTs */
#define MDR_SIR_MODE 0x00000001 /* IrDA UART only */
#define MDR_AUTOBAUDING_MODE 0x00000002 /* Modem UART only */
#define MDR_RESET_MODE 0x00000007 /* Both IrDA and Modem UARTs */
/* SPI **********************************************************************/
#define MAX_SPI 3
#define SPI_REGISTER_BASE 0xffff2000
/* ARMIO ********************************************************************/
/* Timers / Watchdog ********************************************************/
#define C5471_TIMER0_CTRL 0xffff2a00
#define C5471_TIMER0_CNT 0xffff2a04
#define C5471_TIMER1_CTRL 0xffff2b00
#define C5471_TIMER1_CNT 0xffff2b04
#define C5471_TIMER2_CTRL 0xffff2c00
#define C5471_TIMER2_CNT 0xffff2c04
/* Interrupts ***************************************************************/
#define HAVE_SRC_IRQ_BIN_REG 0
#define INT_FIRST_IO 0xffff2d00
#define INT_IO_RANGE 0x5C
#define IT_REG 0xffff2d00
#define MASK_IT_REG 0xffff2d04
#define SRC_IRQ_REG 0xffff2d08
#define SRC_FIQ_REG 0xffff2d0c
#define SRC_IRQ_BIN_REG 0xffff2d10
#define INT_CTRL_REG 0xffff2d18
#define ILR_IRQ0_REG 0xffff2d1C /* 0-Timer 0 */
#define ILR_IRQ1_REG 0xffff2d20 /* 1-Timer 1 */
#define ILR_IRQ2_REG 0xffff2d24 /* 2-Timer 2 */
#define ILR_IRQ3_REG 0xffff2d28 /* 3-GPIO0 */
#define ILR_IRQ4_REG 0xffff2d2c /* 4-Ethernet */
#define ILR_IRQ5_REG 0xffff2d30 /* 5-KBGPIO[7:0] */
#define ILR_IRQ6_REG 0xffff2d34 /* 6-Uart serial */
#define ILR_IRQ7_REG 0xffff2d38 /* 7-Uart IRDA */
#define ILR_IRQ8_REG 0xffff2d3c /* 8-KBGPIO[15:8] */
#define ILR_IRQ9_REG 0xffff2d40 /* 9-GPIO3 */
#define ILR_IRQ10_REG 0xffff2d44 /* 10-GPIO2 */
#define ILR_IRQ11_REG 0xffff2d48 /* 11-I2C */
#define ILR_IRQ12_REG 0xffff2d4c /* 12-GPIO1 */
#define ILR_IRQ13_REG 0xffff2d50 /* 13-SPI */
#define ILR_IRQ14_REG 0xffff2d54 /* 14-GPIO[19:4] */
#define ILR_IRQ15_REG 0xffff2d58 /* 15-API */
/* CLKM *********************************************************************/
#define CLKM 0xffff2f00
#define CLKM_CTL_RST 0xffff2f10
#define CLKM_RESET 0xffff2f18
#define CLKM_RESET_EIM 0x00000008
#define CLKM_EIM_CLK_STOP 0x00000010
#define CLKM_CTL_RST_LEAD_RESET 0x00000000
#define CLKM_CTL_RST_EXT_RESET 0x00000002
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#endif /* __ARCH_ARM_SRC_CALYPSO_CHIP_H */

View File

@ -1,230 +0,0 @@
/****************************************************************************
* arch/arm/src/calypso/clock.c
* Driver for Calypso clock management
*
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
*
* This source code is derivated from Osmocom-BB project and was
* relicensed as BSD with permission from original authors.
*
* 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.
*
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdio.h>
//#define DEBUG
#include <arch/calypso/debug.h>
#include <arch/calypso/memory.h>
#include <arch/calypso/clock.h>
#include "up_arch.h"
#define REG_DPLL 0xffff9800
#define DPLL_LOCK (1 << 0)
#define DPLL_BREAKLN (1 << 1)
#define DPLL_BYPASS_DIV_SHIFT 2 /* 2 bits */
#define DPLL_PLL_ENABLE (1 << 4)
#define DPLL_PLL_DIV_SHIFT 5 /* 2 bits */
#define DPLL_PLL_MULT_SHIFT 7 /* 5 bits */
#define DPLL_TEST (1 << 12)
#define DPLL_IOB (1 << 13) /* Initialize on break */
#define DPLL_IAI (1 << 14) /* Initialize after Idle */
#define BASE_ADDR_CLKM 0xfffffd00
#define CLKM_REG(m) (BASE_ADDR_CLKM+(m))
enum clkm_reg
{
CNTL_ARM_CLK = 0,
CNTL_CLK = 2,
CNTL_RST = 4,
CNTL_ARM_DIV = 8,
};
/* CNTL_ARM_CLK */
#define ARM_CLK_BIG_SLEEP (1 << 0) /* MCU Master Clock enabled? */
#define ARM_CLK_CLKIN_SEL0 (1 << 1) /* MCU source clock (0 = DPLL output, 1 = VTCXO or CLKIN */
#define ARM_CLK_CLKIN_SEL (1 << 2) /* 0 = VTCXO or 1 = CLKIN */
#define ARM_CLK_MCLK_DIV5 (1 << 3) /* enable 1.5 or 2.5 division factor */
#define ARM_CLK_MCLK_DIV_SHIFT 4 /* 3 bits */
#define ARM_CLK_DEEP_POWER_SHIFT 8
#define ARM_CLK_DEEP_SLEEP 12
/* CNTL_CLK */
#define CLK_IRQ_CLK_DIS (1 << 0) /* IRQ clock control (0 always, 1 according ARM_MCLK_EN) */
#define CLK_BRIDGE_CLK_DIS (1 << 1)
#define CLK_TIMER_CLK_DIS (1 << 2)
#define CLK_DPLL_DIS (1 << 3) /* 0: DPLL is not stopped during SLEEP */
#define CLK_CLKOUT_EN (1 << 4) /* Enable CLKOUT output pins */
#define CLK_EN_IDLE3_FLG (1 << 5) /* DSP idle flag control (1 =
* SAM/HOM register forced to HOM when DSP IDLE3) */
#define CLK_VCLKOUT_DIV2 (1 << 6) /* 1: VCLKOUT-FR is divided by 2 */
#define CLK_VTCXO_DIV2 (1 << 7) /* 1: VTCXO is dividied by 2 */
#define BASE_ADDR_MEMIF 0xfffffb00
#define MEMIF_REG(x) (BASE_ADDR_MEMIF+(x))
enum memif_reg
{
API_RHEA_CTL = 0x0e,
EXTRA_CONF = 0x10,
};
static void dump_reg16(uint32_t addr, char *name)
{
printf("%s=0x%04x\n", name, getreg16(addr));
}
void calypso_clk_dump(void)
{
dump_reg16(REG_DPLL, "REG_DPLL");
dump_reg16(CLKM_REG(CNTL_ARM_CLK), "CNTL_ARM_CLK");
dump_reg16(CLKM_REG(CNTL_CLK), "CNTL_CLK");
dump_reg16(CLKM_REG(CNTL_RST), "CNTL_RST");
dump_reg16(CLKM_REG(CNTL_ARM_DIV), "CNTL_ARM_DIV");
}
void calypso_pll_set(uint16_t inp)
{
uint8_t mult = inp >> 8;
uint8_t div = inp & 0xff;
uint16_t reg = getreg16(REG_DPLL);
reg &= ~0x0fe0;
reg |= (div & 0x3) << DPLL_PLL_DIV_SHIFT;
reg |= (mult & 0x1f) << DPLL_PLL_MULT_SHIFT;
reg |= DPLL_PLL_ENABLE;
putreg16(reg, REG_DPLL);
}
void calypso_reset_set(enum calypso_rst calypso_rst, int active)
{
uint8_t reg = getreg8(CLKM_REG(CNTL_RST));
if (active)
reg |= calypso_rst;
else
reg &= ~calypso_rst;
putreg8(reg, CLKM_REG(CNTL_RST));
}
int calypso_reset_get(enum calypso_rst calypso_rst)
{
uint8_t reg = getreg8(CLKM_REG(CNTL_RST));
if (reg & calypso_rst)
return 1;
else
return 0;
}
void calypso_clock_set(uint8_t vtcxo_div2, uint16_t inp, enum mclk_div mclk_div)
{
uint16_t cntl_clock = getreg16(CLKM_REG(CNTL_CLK));
uint16_t cntl_arm_clk = getreg16(CLKM_REG(CNTL_ARM_CLK));
/* First set the vtcxo_div2 */
cntl_clock &= ~CLK_VCLKOUT_DIV2;
if (vtcxo_div2)
cntl_clock |= CLK_VTCXO_DIV2;
else
cntl_clock &= ~CLK_VTCXO_DIV2;
putreg16(cntl_clock, CLKM_REG(CNTL_CLK));
/* Then configure the MCLK divider */
cntl_arm_clk &= ~ARM_CLK_CLKIN_SEL0;
if (mclk_div & 0x80)
{
mclk_div &= ~0x80;
cntl_arm_clk |= ARM_CLK_MCLK_DIV5;
}
else
cntl_arm_clk &= ~ARM_CLK_MCLK_DIV5;
cntl_arm_clk &= ~(0x7 << ARM_CLK_MCLK_DIV_SHIFT);
cntl_arm_clk |= (mclk_div << ARM_CLK_MCLK_DIV_SHIFT);
putreg16(cntl_arm_clk, CLKM_REG(CNTL_ARM_CLK));
/* Then finally set the PLL */
calypso_pll_set(inp);
}
void calypso_mem_cfg(enum calypso_bank bank, uint8_t ws,
enum calypso_mem_width width, int we)
{
putreg16((ws & 0x1f) | ((width & 3) << 5) | ((we & 1) << 7),
BASE_ADDR_MEMIF + bank);
}
void calypso_bootrom(int enable)
{
uint16_t conf = getreg16(MEMIF_REG(EXTRA_CONF));
conf |= (3 << 8);
if (enable)
conf &= ~(1 << 9);
putreg16(conf, MEMIF_REG(EXTRA_CONF));
}
void calypso_debugunit(int enable)
{
uint16_t conf = getreg16(MEMIF_REG(EXTRA_CONF));
if (enable)
conf &= ~(1 << 11);
else
conf |= (1 << 11);
putreg16(conf, MEMIF_REG(EXTRA_CONF));
}
#define REG_RHEA_CNTL 0xfffff900
#define REG_API_CNTL 0xfffff902
#define REG_ARM_RHEA 0xfffff904
void calypso_rhea_cfg(uint8_t fac0, uint8_t fac1, uint8_t timeout,
uint8_t ws_h, uint8_t ws_l, uint8_t w_en0, uint8_t w_en1)
{
putreg16(fac0 | (fac1 << 4) | (timeout << 8), REG_RHEA_CNTL);
putreg16(ws_h | (ws_l << 5), REG_API_CNTL);
putreg16(w_en0 | (w_en1 << 1), REG_ARM_RHEA);
}

View File

@ -191,11 +191,6 @@
# define _DATA_INIT &_eronly
# define _START_DATA &_sdata
# define _END_DATA &_edata
#ifdef CONFIG_SMP
# define _START_NOCACHE &_snocache
# define _END_NOCACHE &_enocache
#endif
#endif
/* This is the value used to mark the stack for subsequent stack monitoring
@ -284,11 +279,6 @@ EXTERN uint32_t _edata; /* End+1 of .data */
EXTERN uint32_t _sbss; /* Start of .bss */
EXTERN uint32_t _ebss; /* End+1 of .bss */
#ifdef CONFIG_SMP
EXTERN uint32_t _snocache; /* Start of .nocache */
EXTERN uint32_t _enocache; /* End+1 of .nocache */
#endif
/* Sometimes, functions must be executed from RAM. In this case, the following
* macro may be used (with GCC!) to specify a function that will execute from
* RAM. For example,

View File

@ -281,7 +281,8 @@ static void efm32_leuart_setbaud(uintptr_t base, uint32_t baud)
void efm32_lowsetup(void)
{
#if defined(HAVE_UART_DEVICE) || defined(HAVE_LEUART_DEVICE)
#if defined(HAVE_UART_DEVICE) || defined(HAVE_LEUART_DEVICE) || \
defined(HAVE_SPI_DEVICE)
uint32_t regval;
#endif

View File

@ -126,9 +126,7 @@
* address in the top-level memory map are candidates for other mapping uses:
*
* 00018000-000fffff Reserved -- Not used
* 00400000-007fffff Reserved -- Used as the virtual address an inter-CPU,
* un-cached memory region in SMP
* configurations
* 00400000-007fffff Reserved -- Not used
* 00d00000-00ffffff Reserved -- Not used
* 0220c000-023fffff Reserved -- Not used
* 80000000-efffffff Reserved -- Level 2 page table (See below)
@ -929,8 +927,6 @@
* the address space.
*/
#define INTERCPU_L2_PAGES 1 /* Pages allowed for inter-processor communications */
#ifndef CONFIG_ARCH_LOWVECTORS
/* Memory map
* VIRTUAL ADDRESS RANGE L1 PG TABLE L2 PG TABLE DESCRIPTION
@ -938,10 +934,6 @@
* ---------- ---------- ------------ ----------------------------
* 0x80000000 0x803fffff 0x000002000 0x000000400 Vectors (1MiB)
* 0x80100000 0x806fffff 0x000002400 0x000001800 Paging (6MiB)
*
* If SMP is enabled, then 1MiB of address spaces for the INTERCPU_L2_PAGES
* pages are taken from the end of the Paging L2 page table to hold non-
* cacheable, inter-processor communication data.
*/
/* Vector L2 page table offset/size */
@ -959,18 +951,10 @@
# define VECTOR_L2_END_PADDR (VECTOR_L2_PBASE + VECTOR_L2_SIZE)
# define VECTOR_L2_END_VADDR (VECTOR_L2_VBASE + VECTOR_L2_SIZE)
# if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Paging L2 page table offset/size */
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001400
# else
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001800
# endif
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001800
#else
/* Memory map
@ -978,24 +962,12 @@
* START END OFFSET SIZE
* ---------- ---------- ------------ ----------------------------
* 0x80000000 0x806fffff 0x000002000 0x000001c00 Paging (7MiB)
*
* If SMP is enabled, then 1MiB of address spaces for the INTERCPU_L2_PAGES
* pages are taken from the end of the Paging L2 page table to hold non-
* cacheable, inter-processor communication data.
*/
# if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001800
# else
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001c00
# endif
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001c00
#endif
@ -1013,23 +985,6 @@
#define PGTABLE_L2_END_PADDR (PGTABLE_L2_PBASE + PGTABLE_L2_SIZE)
#define PGTABLE_L2_END_VADDR (PGTABLE_L2_VBASE + PGTABLE_L2_SIZE)
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Non-cached inter-processor communication data */
# define INTERCPU_L2_OFFSET (PGTABLE_L2_OFFSET + PGTABLE_L2_SIZE)
# define INTERCPU_L2_SIZE (0x00000400)
/* Non-cached inter-processor communication page table base addresses */
# define INTERCPU_L2_PBASE (PGTABLE_BASE_PADDR + INTERCPU_L2_OFFSET)
# define INTERCPU_L2_VBASE (PGTABLE_BASE_VADDR + INTERCPU_L2_OFFSET)
/* Non-cached inter-processor communication end addresses */
# define INTERCPU_L2_END_PADDR (INTERCPU_L2_PBASE + INTERCPU_L2_SIZE)
# define INTERCPU_L2_END_VADDR (INTERCPU_L2_VBASE + INTERCPU_L2_SIZE)
#endif
/* Base address of the interrupt vector table.
*
* IMX_VECTOR_PADDR - Unmapped, physical address of vector table in SRAM
@ -1052,8 +1007,7 @@
* START END CONTENT
* ---------- ---------- ---------------------------
* 0x00000000 0x00010000 Vectors (VECTOR_TABLE_SIZE)
* 0x00010000 0x00011000 Inter-CPU communications
* 0x00011000 0x0003c000 Unused
* 0x00010000 0x0003c000 Unused
* 0x0003c000 0x00004000 Page table (PGTABLE_SIZE)
*/
@ -1061,27 +1015,13 @@
# define IMX_VECTOR_VSRAM IMX_OCRAM_VBASE
# define IMX_VECTOR_VADDR 0x00000000
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Inter-processor communications.
*
* NOTICE that we use the unused virtual address space at 0x00400000 for
* the inter-CPU virtual communication area.
*/
# define INTERCPU_PADDR (IMX_VECTOR_PADDR + VECTOR_TABLE_SIZE)
# define INTERCPU_VADDR (0x00400000)
# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12)
# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM + VECTOR_TABLE_SIZE)
#endif
#else /* Vectors located at 0xffff:0000 -- this probably does not work */
/* OCRAM Memory Map:
* ---------- ---------- ---------------------------
* START END CONTENT
* ---------- ---------- ---------------------------
* 0x00000000 0x00004000 Page table (PGTABLE_SIZE)
* 0x00004000 0x0002f000 Unused
* 0x0002f000 0x00030000 Inter-CPU communications
* 0x00004000 0x00030000 Unused
* 0x00030000 0x00010000 Vectors (VECTOR_TABLE_SIZE)
*/
@ -1089,18 +1029,6 @@
# define IMX_VECTOR_VSRAM (IMX_OCRAM_VBASE + IMX_OCRAM_SIZE - VECTOR_TABLE_SIZE)
# define IMX_VECTOR_VADDR 0xffff0000
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Inter-processor communications
*
* NOTICE that we use the unused virtual address space at 0x00400000 for
* the inter-CPU virtual communication area.
*/
# define INTERCPU_PADDR (IMX_VECTOR_PADDR - INTERCPU_L2_SIZE)
# define INTERCPU_VADDR (0x00400000)
# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12)
# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM - INTERCPU_L2_SIZE)
#endif
#endif
/************************************************************************************

View File

@ -235,48 +235,6 @@ static void imx_vectormapping(void)
# define imx_vectormapping()
#endif
/****************************************************************************
* Name: imx_intercpu_mapping
*
* Description:
* Setup a special mapping for the non-cached, inter-cpu communications
* area.
*
****************************************************************************/
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
static void imx_intercpu_mapping(void)
{
uint32_t intercpu_paddr = INTERCPU_PADDR & PTE_SMALL_PADDR_MASK;
uint32_t intercpu_vaddr = INTERCPU_VADDR & PTE_SMALL_PADDR_MASK;
uint32_t end_paddr = INTERCPU_PADDR + INTERCPU_SIZE;
DEBUGASSERT(intercpu_vaddr == (uint32_t)&_snocache);
/* We want to keep the inter-cpu region in on-chip RAM (OCRAM). The
* i.MX6 has 256Kb of OCRAM positioned at physical address 0x0090:0000.
*/
while (intercpu_paddr < end_paddr)
{
mmu_l2_setentry(INTERCPU_L2_VBASE, intercpu_paddr, intercpu_vaddr,
MMU_L2_INTERCPUFLAGS);
intercpu_paddr += 4096;
intercpu_vaddr += 4096;
}
/* Now set the level 1 descriptor to refer to the level 2 page table. */
mmu_l1_setentry(INTERCPU_L2_PBASE & PMD_PTE_PADDR_MASK,
INTERCPU_VADDR & PMD_PTE_PADDR_MASK,
MMU_L1_INTERCPUFLAGS);
}
#else
/* No inter-cpu communications area */
# define imx_intercpu_mapping()
#endif
/****************************************************************************
* Name: imx_copyvectorblock
*
@ -477,15 +435,6 @@ void arm_boot(void)
imx_vectormapping();
PROGRESS('D');
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Provide a special mapping for the OCRAM interrupt vector positioned in
* high memory.
*/
imx_intercpu_mapping();
PROGRESS('E');
#endif
#ifdef CONFIG_ARCH_RAMFUNCS
/* Copy any necessary code sections from FLASH to RAM. The correct
* destination in OCRAM is given by _sramfuncs and _eramfuncs. The
@ -498,14 +447,14 @@ void arm_boot(void)
*dest++ = *src++;
}
PROGRESS('F');
PROGRESS('E');
/* Flush the copied RAM functions into physical RAM so that will
* be available when fetched into the I-Cache.
*/
arch_clean_dcache((uintptr_t)&_sramfuncs, (uintptr_t)&_eramfuncs)
PROGRESS('G');
PROGRESS('F');
#endif
/* Setup up vector block. _vector_start and _vector_end are exported from
@ -513,23 +462,23 @@ void arm_boot(void)
*/
imx_copyvectorblock();
PROGRESS('H');
PROGRESS('G');
/* Disable the watchdog timer */
imx_wdtdisable();
PROGRESS('I');
PROGRESS('H');
/* Initialize clocking to settings provided by board-specific logic */
imx_clockconfig();
PROGRESS('J');
PROGRESS('I');
#ifdef CONFIG_ARCH_FPU
/* Initialize the FPU */
arm_fpuconfig();
PROGRESS('K');
PROGRESS('J');
#endif
/* Perform board-specific memroy initialization, This must include
@ -541,7 +490,7 @@ void arm_boot(void)
*/
imx_memory_initialize();
PROGRESS('L');
PROGRESS('K');
#ifdef NEED_SDRAM_REMAPPING
/* SDRAM was configured in a temporary state to support low-level
@ -550,7 +499,7 @@ void arm_boot(void)
*/
imx_remap();
PROGRESS('M');
PROGRESS('L');
#endif
#ifdef CONFIG_BOOT_SDRAM_DATA
@ -559,7 +508,7 @@ void arm_boot(void)
*/
arm_data_initialize();
PROGRESS('N');
PROGRESS('M');
#endif
/* Perform board-specific device initialization. This would include
@ -567,23 +516,12 @@ void arm_boot(void)
*/
imx_board_initialize();
PROGRESS('O');
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Initialize the uncached, inter-CPU communications area */
for (dest = &_snocache; dest < &_enocache; )
{
*dest++ = 0;
}
PROGRESS('P');
#endif
PROGRESS('N');
/* Perform common, low-level chip initialization (might do nothing) */
imx_lowsetup();
PROGRESS('Q');
PROGRESS('O');
#ifdef USE_EARLYSERIALINIT
/* Perform early serial initialization if we are going to use the serial
@ -591,7 +529,7 @@ void arm_boot(void)
*/
imx_earlyserialinit();
PROGRESS('R');
PROGRESS('P');
#endif
/* Now we can enable all other CPUs. The enabled CPUs will start execution
@ -600,6 +538,6 @@ void arm_boot(void)
*/
imx_cpu_enable();
PROGRESS('S');
PROGRESS('Q');
PROGRESS('\n');
}

View File

@ -115,10 +115,6 @@ static void up_output_compare(uint32_t sr, uint32_t of)
if ((sr & of) != 0)
{
/* Clear the pending output compare interrupt */
putreg32(of, IMX_GPT_SR);
/* Process timer interrupt event */
sched_process_timer();
@ -140,9 +136,16 @@ static void up_output_compare(uint32_t sr, uint32_t of)
int up_timerisr(int irq, uint32_t *regs)
{
/* Sample the SR (once) and process all pending output compare interrupt */
/* Sample the SR (once) */
uint32_t sr = getreg32(IMX_GPT_SR);
/* Clear GPT status register */
putreg32(sr, IMX_GPT_SR);
/* Process all pending output compare interrupt */
up_output_compare(sr, GPT_INT_OF1);
up_output_compare(sr, GPT_INT_OF2);
up_output_compare(sr, GPT_INT_OF3);

View File

@ -70,7 +70,7 @@ CMN_CSRCS += up_dumpnvic.c
endif
CHIP_ASRCS =
CHIP_CSRCS = kl_clockconfig.c kl_gpio.c kl_idle.c kl_irq.c kl_getc.c
CHIP_CSRCS = kl_clockconfig.c kl_gpio.c kl_idle.c kl_irq.c
CHIP_CSRCS += kl_lowputc.c kl_serial.c kl_start.c kl_cfmconfig.c
ifneq ($(CONFIG_SCHED_TICKLESS),y)

View File

@ -71,7 +71,7 @@ endif
CHIP_ASRCS =
CHIP_CSRCS = lpc11_clockconfig.c lpc11_gpio.c lpc11_i2c.c lpc11_idle.c
CHIP_CSRCS += lpc11_irq.c lpc11_lowputc.c lpc11_getc.c lpc11_serial.c
CHIP_CSRCS += lpc11_irq.c lpc11_lowputc.c lpc11_serial.c
CHIP_CSRCS += lpc11_spi.c lpc11_ssp.c lpc11_start.c
# Configuration-dependent LPC11xx files

View File

@ -1,47 +0,0 @@
/************************************************************************************
* arch/arm/src/lpc11/lpc11_getc.h
*
* Copyright (C) 2015, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __ARCH_ARM_SRC_LPC11XX_LPC11_GETC_H
#define __ARCH_ARM_SRC_LPC11XX_LPC11_GETC_H
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include "lpc11_serial.h"
#include "chip/lpc11_uart.h"
#endif /* __ARCH_ARM_SRC_LPC11XX_LPC11_GETC_H */

View File

@ -2086,6 +2086,7 @@ static int lpc17_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlo
rlong[2] = getreg32(LPC17_SDCARD_RESP2);
rlong[3] = getreg32(LPC17_SDCARD_RESP3);
}
return ret;
}

View File

@ -603,23 +603,23 @@
#define PINCONF_QEI_PHA (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_3)
#define PINCONF_QEI_PHB (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_2)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_POW_1 (PINCONF_FUNC5|PINCONF_PINSD|PINCONF_PIN_1)
#define PINCONF_SD_POW_2 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_5)
#define PINCONF_SD_POW_3 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_9)

View File

@ -603,23 +603,23 @@
#define PINCONF_QEI_PHA (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_3)
#define PINCONF_QEI_PHB (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_2)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_POW_1 (PINCONF_FUNC5|PINCONF_PINSD|PINCONF_PIN_1)
#define PINCONF_SD_POW_2 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_5)
#define PINCONF_SD_POW_3 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_9)

View File

@ -603,23 +603,23 @@
#define PINCONF_QEI_PHA (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_3)
#define PINCONF_QEI_PHB (PINCONF_FUNC1|PINCONF_PINSA|PINCONF_PIN_2)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_CD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_13)
#define PINCONF_SD_CD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_8)
#define PINCONF_SD_CLK (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_0)
#define PINCONF_SD_CMD_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_6)
#define PINCONF_SD_CMD_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_10)
#define PINCONF_SD_DAT0_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_9)
#define PINCONF_SD_DAT0_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_4)
#define PINCONF_SD_DAT1_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_10)
#define PINCONF_SD_DAT1_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_5)
#define PINCONF_SD_DAT2_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_11)
#define PINCONF_SD_DAT2_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_6)
#define PINCONF_SD_DAT3_1 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINS1|PINCONF_PIN_12)
#define PINCONF_SD_DAT3_2 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_7)
#define PINCONF_SD_DAT4 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_11)
#define PINCONF_SD_DAT5 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_12)
#define PINCONF_SD_DAT6 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_13)
#define PINCONF_SD_DAT7 (PINCONF_FUNC7|PINCONF_INBUFFER|PINCONF_GLITCH|PINCONF_SLEW_FAST|PINCONF_PINSC|PINCONF_PIN_14)
#define PINCONF_SD_POW_1 (PINCONF_FUNC5|PINCONF_PINSD|PINCONF_PIN_1)
#define PINCONF_SD_POW_2 (PINCONF_FUNC7|PINCONF_PINS1|PINCONF_PIN_5)
#define PINCONF_SD_POW_3 (PINCONF_FUNC7|PINCONF_PINSC|PINCONF_PIN_9)

View File

@ -44,6 +44,7 @@
#include <debug.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/spinlock.h>

View File

@ -1907,16 +1907,35 @@ static int mcan_del_extfilter(FAR struct sam_mcan_s *priv, int ndx)
DEBUGASSERT(priv != NULL && priv->config != NULL);
config = priv->config;
DEBUGASSERT(ndx < config->nextfilters);
/* Check user Parameters */
DEBUGASSERT(ndx >= 0 || ndx < config->nextfilters);
if (ndx < 0 || ndx >= config->nextfilters)
{
return -EINVAL;
}
/* Get exclusive excess to the MCAN hardware */
mcan_dev_lock(priv);
/* Release the filter */
word = ndx >> 5;
bit = ndx & 0x1f;
/* Check if this filter is really assigned */
if ((priv->extfilters[word] & (1 << bit)) == 0)
{
/* No, error out */
mcan_dev_unlock(priv);
return -ENOENT;
}
/* Release the filter */
priv->extfilters[word] &= ~(1 << bit);
DEBUGASSERT(priv->nextalloc > 0);
@ -2137,16 +2156,35 @@ static int mcan_del_stdfilter(FAR struct sam_mcan_s *priv, int ndx)
DEBUGASSERT(priv != NULL && priv->config != NULL);
config = priv->config;
DEBUGASSERT(ndx < config->nstdfilters);
/* Check Userspace Parameters */
DEBUGASSERT(ndx >= 0 || ndx < config->nstdfilters);
if (ndx < 0 || ndx >= config->nstdfilters)
{
return -EINVAL;
}
/* Get exclusive excess to the MCAN hardware */
mcan_dev_lock(priv);
/* Release the filter */
word = ndx >> 5;
bit = ndx & 0x1f;
/* Check if this filter is really assigned */
if ((priv->stdfilters[word] & (1 << bit)) == 0)
{
/* No, error out */
mcan_dev_unlock(priv);
return -ENOENT;
}
/* Release the filter */
priv->stdfilters[word] &= ~(1 << bit);
DEBUGASSERT(priv->nstdalloc > 0);
@ -3388,6 +3426,19 @@ static void mcan_interrupt(FAR struct can_dev_s *dev)
{
canerr("ERROR: TX %08x\n", pending & MCAN_TXERR_INTS);
/* An Acknowledge-Error will occur if for example the device
* is not connected to the bus.
*
* The CAN-Standard states that the Chip has to retry the
* message forever, which will produce an ACKE every time.
* To prevent this Interrupt-Flooding and the high CPU-Load
* we disable the ACKE here as long we didn't transfer at
* least one message successfully (see MCAN_INT_TC below).
*/
ie &= ~MCAN_INT_ACKE;
mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
/* Clear the error indications */
mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_TXERR_INTS);
@ -3441,6 +3492,17 @@ static void mcan_interrupt(FAR struct can_dev_s *dev)
if ((pending & MCAN_INT_TC) != 0)
{
/* Check if we have disabled the ACKE in the error-handling above
* (see MCAN_TXERR_INTS) to prevent Interrupt-Flooding and
* re-enable the error interrupt here again.
*/
if ((ie & MCAN_INT_ACKE) == 0)
{
ie |= MCAN_INT_ACKE;
mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
}
/* Clear the pending TX completion interrupt (and all
* other TX-related interrupts)
*/

View File

@ -110,7 +110,7 @@ CHIP_ASRCS =
CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c
CHIP_CSRCS += stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c
CHIP_CSRCS += stm32_irq.c stm32_dma.c stm32_lowputc.c stm32_getc.c
CHIP_CSRCS += stm32_irq.c stm32_dma.c stm32_lowputc.c
CHIP_CSRCS += stm32_serial.c stm32_spi.c stm32_sdio.c stm32_tim.c
CHIP_CSRCS += stm32_waste.c stm32_ccm.c stm32_uid.c stm32_capture.c

View File

@ -78,7 +78,6 @@
#include "stm32_usbdev.h"
#include "stm32_wdg.h"
#include "stm32_lowputc.h"
#include "stm32_getc.h"
#include "stm32_eth.h"
#endif /* __ARCH_ARM_SRC_STM32_STM32_H */

View File

@ -295,6 +295,10 @@
# define SRAM1_END 0x20018000
# elif defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429)
# define SRAM1_END 0x20030000
# elif defined(CONFIG_STM32_STM32F446)
# define SRAM1_END 0x20020000
# elif defined(CONFIG_STM32_STM32F469)
# define SRAM1_END 0x20050000
# else
# define SRAM1_END 0x20020000
# endif

View File

@ -313,7 +313,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
addr -= STM32_FLASH_BASE;
}
if ((addr+count) >= STM32_FLASH_SIZE)
if ((addr+count) > STM32_FLASH_SIZE)
{
return -EFAULT;
}

View File

@ -1,121 +0,0 @@
/****************************************************************************
* arch/arm/src/stm32/stm32_getc.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 <stdint.h>
#include <arch/board/board.h>
#include "up_internal.h"
#include "up_arch.h"
#include "chip.h"
#include "stm32.h"
#include "stm32_rcc.h"
#include "stm32_gpio.h"
#include "stm32_uart.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Select U[S]ART console base address */
#ifdef HAVE_CONSOLE
# if defined(CONFIG_USART1_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_USART1_BASE
# elif defined(CONFIG_USART2_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_USART2_BASE
# elif defined(CONFIG_USART3_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_USART3_BASE
# elif defined(CONFIG_UART4_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_UART4_BASE
# elif defined(CONFIG_UART5_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_UART5_BASE
# elif defined(CONFIG_USART6_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_USART6_BASE
# elif defined(CONFIG_UART7_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_UART7_BASE
# elif defined(CONFIG_UART8_SERIAL_CONSOLE)
# define STM32_CONSOLE_BASE STM32_UART8_BASE
# endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_getc
*
* Description:
* Read one byte from the serial console
*
* REVIST: If used with the serial driver enabled, then this could
* interfere with the serial driver operations. Serial interrupts should
* be disabled when this function executes in that case.
*
****************************************************************************/
int up_getc(void)
{
uint32_t ch = 0;
#ifdef HAVE_CONSOLE
/* While there is any error, read and discard bytes to clear the errors */
while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) &
(USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE)) != 0)
{
(void)getreg32(STM32_CONSOLE_BASE + STM32_USART_RDR_OFFSET);
}
/* Wait until the RX data register has a character to be read */
while ((getreg32(STM32_CONSOLE_BASE + STM32_USART_SR_OFFSET) & USART_SR_RXNE) == 0);
/* Then read the character */
ch = getreg32(STM32_CONSOLE_BASE + STM32_USART_RDR_OFFSET);
#endif /* HAVE_CONSOLE */
return (int)ch;
}

View File

@ -2209,6 +2209,7 @@ static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlo
rlong[2] = getreg32(STM32_SDIO_RESP3);
rlong[3] = getreg32(STM32_SDIO_RESP4);
}
return ret;
}
@ -2577,12 +2578,14 @@ static int stm32_dmapreflight(FAR struct sdio_dev_s *dev,
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
#if !defined(CONFIG_STM32_STM32F40XX)
/* Wide bus operation is required for DMA */
if (!priv->widebus)
{
return -EINVAL;
}
#endif
/* DMA must be possible to the buffer */

View File

@ -1945,11 +1945,11 @@ static int up_interrupt_common(struct up_dev_s *priv)
static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
{
#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) \
|| defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT)
|| defined(CONFIG_STM32_SERIALBRK_BSDCOMPAT)
struct inode *inode = filep->f_inode;
struct uart_dev_s *dev = inode->i_private;
#endif
#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT)
#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32_SERIALBRK_BSDCOMPAT)
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
#endif
int ret = OK;

View File

@ -743,7 +743,8 @@ static void stm32_stdclockconfig(void)
{
}
#if defined(PWR_CSR_ODRDY)
#if defined(CONFIG_STM32_STM32F429) || defined(CONFIG_STM32_STM32F446) || \
defined(CONFIG_STM32_STM32F469)
/* Enable the Over-drive to extend the clock frequency to 180 Mhz */

View File

@ -997,7 +997,7 @@
#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN13)
#define GPIO_SPI2_SCK_4 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTD|GPIO_PIN3)
#define GPIO_SPI2_SCK_5 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTI|GPIO_PIN1)
#define GPIO_SPI2_SCK_6 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTIA|GPIO_PIN12)
#define GPIO_SPI2_SCK_6 (GPIO_ALT|GPIO_AF5|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN12)
#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN4)
#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN11)

View File

@ -107,6 +107,23 @@
#define CC_PWMDIV_64 (0x5) /* (Value) Divided by 64 */
#define TIVA_PWMn_CTL_ENABLE (0) /* (Bit) PWM Block Enable */
#define CTL_DISABLE (0) /* (Value) Disable */
#define CTL_ENABLE (1) /* (Value) Enable */
#define INTEN_GEN3 (3) /* (Bit) Enable PWM GEN3 Interrupt */
#define INTEN_GEN2 (2) /* (Bit) Enable PWM GEN2 Interrupt */
#define INTEN_GEN1 (1) /* (Bit) Enable PWM GEN1 Interrupt */
#define INTEN_GEN0 (0) /* (Bit) Enable PWM GEN0 Interrupt */
#define INT_DISABLE (0) /* (Value) Disable */
#define INT_ENABLE (1) /* (Value) Enable */
#define INTCMPBD (5) /* (Bit) Interrupt for Counter=PWMnCMPB Down */
#define INTCMPBU (4) /* (Bit) Interrupt for Counter=PWMnCMPB Up */
#define INTCMPAD (3) /* (Bit) Interrupt for Counter=PWMnCMPA Down */
#define INTCMPAU (2) /* (Bit) Interrupt for Counter=PWMnCMPA Up */
#define INTCNTLOAD (1) /* (Bit) Interrupt for Counter=PWMnLOAD */
#define INTCNTZERO (0) /* (Bit) Interrupt for Counter=0 */
#define INT_CLR (0) /* (Value) Bit Clear */
#define INT_SET (1) /* (Value) Bit Set */
#endif /* __ARCH_ARM_SRC_TIVA_CHIP_TIVA_PWM_H */

View File

@ -85,21 +85,57 @@ struct tiva_pwm_chan_s
uint8_t generator_id;
uintptr_t generator_base;
uint8_t channel_id;
#ifdef CONFIG_PWM_PULSECOUNT
bool inited;
uint8_t irq;
uint32_t count;
uint32_t cur_count;
FAR void *handle;
#endif
};
/************************************************************************************
* Private Function Prototypes
************************************************************************************/
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN0)
static int tiva_pwm_gen0_interrupt(int irq, FAR void *context);
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN2)
static int tiva_pwm_gen1_interrupt(int irq, FAR void *context);
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN4)
static int tiva_pwm_gen2_interrupt(int irq, FAR void *context);
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN6)
static int tiva_pwm_gen3_interrupt(int irq, FAR void *context);
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && \
(defined(CONFIG_TIVA_PWM0_CHAN0) || defined(CONFIG_TIVA_PWM0_CHAN2) || \
defined(CONFIG_TIVA_PWM0_CHAN4) || defined(CONFIG_TIVA_PWM0_CHAN6))
static int tiva_pwm_interrupt(struct tiva_pwm_chan_s *chan);
#endif
static inline void tiva_pwm_putreg(struct tiva_pwm_chan_s *chan,
unsigned int offset, uint32_t regval);
static inline uint32_t tiva_pwm_getreg(struct tiva_pwm_chan_s *chan,
unsigned int offset);
static inline int tiva_pwm_timer(FAR struct tiva_pwm_chan_s *chan,
FAR const struct pwm_info_s *info);
static int tiva_pwm_setup(FAR struct pwm_lowerhalf_s *dev);
static int tiva_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
#ifdef CONFIG_PWM_PULSECOUNT
static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info, FAR void *handle);
#else
static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info);
#endif
static int tiva_pwm_stop(FAR struct pwm_lowerhalf_s *dev);
static int tiva_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
int cmd, unsigned long arg);
@ -108,7 +144,7 @@ static int tiva_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
* Private Data
************************************************************************************/
static uint32_t g_pwm_freq = 15000000;
static uint32_t g_pwm_freq = 1875000;
static uint32_t g_pwm_counter = (1 << 16);
static const struct pwm_ops_s g_pwm_ops =
@ -129,6 +165,13 @@ static struct tiva_pwm_chan_s g_pwm_chan0 =
.generator_id = 0,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 0,
.channel_id = 0,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN0,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -141,6 +184,13 @@ static struct tiva_pwm_chan_s g_pwm_chan1 =
.generator_id = 0,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 0,
.channel_id = 1,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN0,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -153,6 +203,13 @@ static struct tiva_pwm_chan_s g_pwm_chan2 =
.generator_id = 1,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 1,
.channel_id = 2,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN1,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -165,6 +222,13 @@ static struct tiva_pwm_chan_s g_pwm_chan3 =
.generator_id = 1,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 1,
.channel_id = 3,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN1,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -177,6 +241,13 @@ static struct tiva_pwm_chan_s g_pwm_chan4 =
.generator_id = 2,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 2,
.channel_id = 4,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN2,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -189,6 +260,13 @@ static struct tiva_pwm_chan_s g_pwm_chan5 =
.generator_id = 2,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 2,
.channel_id = 5,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN2,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -198,9 +276,16 @@ static struct tiva_pwm_chan_s g_pwm_chan6 =
.ops = &g_pwm_ops,
.controller_id = 0,
.controller_base = TIVA_PWM0_BASE,
.generator_id = 3,
.generator_id = 3,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 3,
.channel_id = 6,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN3,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -213,6 +298,13 @@ static struct tiva_pwm_chan_s g_pwm_chan7 =
.generator_id = 3,
.generator_base = TIVA_PWM0_BASE + TIVA_PWMn_BASE + TIVA_PWMn_INTERVAL * 3,
.channel_id = 7,
#ifdef CONFIG_PWM_PULSECOUNT
.inited = false,
.irq = TIVA_IRQ_PWM0_GEN3,
.count = 0,
.cur_count = 0,
.handle = NULL,
#endif
};
#endif
@ -220,6 +312,76 @@ static struct tiva_pwm_chan_s g_pwm_chan7 =
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: tiva_pwm_gen[n]_interrupt
*
* Description:
* Pulse count interrupt handlers for PWM[n]
*
************************************************************************************/
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN0)
static int tiva_pwm_gen0_interrupt(int irq, FAR void *context)
{
return tiva_pwm_interrupt(&g_pwm_chan0);
}
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN2)
static int tiva_pwm_gen1_interrupt(int irq, FAR void *context)
{
return tiva_pwm_interrupt(&g_pwm_chan2);
}
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN4)
static int tiva_pwm_gen2_interrupt(int irq, FAR void *context)
{
return tiva_pwm_interrupt(&g_pwm_chan4);
}
#endif
#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_TIVA_PWM0_CHAN6)
static int tiva_pwm_gen3_interrupt(int irq, FAR void *context)
{
return tiva_pwm_interrupt(&g_pwm_chan6);
}
#endif
/************************************************************************************
* Name: tiva_pwm_interrupt
*
* Description:
* Common pulse count interrupt handler.
*
************************************************************************************/
#if defined(CONFIG_PWM_PULSECOUNT) && \
(defined(CONFIG_TIVA_PWM0_CHAN0) || defined(CONFIG_TIVA_PWM0_CHAN2) || \
defined(CONFIG_TIVA_PWM0_CHAN4) || defined(CONFIG_TIVA_PWM0_CHAN6))
static int tiva_pwm_interrupt(struct tiva_pwm_chan_s *chan)
{
/* Clear interrupt */
tiva_pwm_putreg(chan, TIVA_PWMn_ISC_OFFSET, INT_SET << INTCMPAD);
/* Count down current pulse count */
chan->cur_count--;
/* Disable PWM generator and reload current pulse count */
if (chan->cur_count == 0)
{
tiva_pwm_putreg(chan, TIVA_PWMn_CTL_OFFSET, CTL_DISABLE << TIVA_PWMn_CTL_ENABLE);
chan->cur_count = chan->count;
pwm_expired(chan->handle);
}
return 0;
}
#endif
/************************************************************************************
* Name: tiva_pwm_getreg
*
@ -251,7 +413,7 @@ static inline void tiva_pwm_putreg(struct tiva_pwm_chan_s *chan,
}
/****************************************************************************
* Name: pwm_setup
* Name: tiva_pwm_setup
*
* Description:
* This method is called when the driver is opened. The lower half driver
@ -288,7 +450,7 @@ static int tiva_pwm_setup(FAR struct pwm_lowerhalf_s *dev)
}
/****************************************************************************
* Name: pwm_shutdown
* Name: tiva_pwm_shutdown
*
* Description:
* This method is called when the driver is closed. The lower half driver
@ -320,7 +482,7 @@ static int tiva_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
}
/****************************************************************************
* Name: pwm_start
* Name: tiva_pwm_start
*
* Description:
* (Re-)initialize the timer resources and start the pulsed output
@ -328,33 +490,117 @@ static int tiva_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
* Input parameters:
* dev - A reference to the lower half PWM driver state structure
* info - A reference to the characteristics of the pulsed output
* handle - This is the handle that was provided to the lower-half
* start() method.
*
* Returned Value:
* Zero on success; a negated errno value on failure
*
****************************************************************************/
#ifdef CONFIG_PWM_PULSECOUNT
static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info, FAR void *handle)
{
FAR struct tiva_pwm_chan_s *chan = (FAR struct tiva_pwm_chan_s *)dev;
pwminfo("start PWM for channel %d\n", chan->channel_id);
/* Save the handle */
chan->handle = handle;
/* Load pulse count and current pulse count
*
* Workaround:
* Count should be add 1 for the first time
*/
chan->count = info->count;
chan->cur_count = info->count;
if (!chan->inited)
{
chan->count++;
chan->cur_count++;
chan->inited = true;
}
/* Count 0 means to generate indefinite number of pulses */
if (info->count == 0)
{
pwm_expired(chan->handle);
/* Disable interrupt */
uint32_t enable = getreg32(chan->controller_base + TIVA_PWM_INTEN_OFFSET);
enable &= ~(INT_ENABLE << chan->generator_id);
putreg32(enable, chan->controller_base + TIVA_PWM_INTEN_OFFSET);
}
else
{
/* Enable interrupt */
uint32_t enable = getreg32(chan->controller_base + TIVA_PWM_INTEN_OFFSET);
enable |= (INT_ENABLE << chan->generator_id);
putreg32(enable, chan->controller_base + TIVA_PWM_INTEN_OFFSET);
}
/* Start the timer */
return tiva_pwm_timer(chan, info);
}
#else
static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info)
{
FAR struct tiva_pwm_chan_s *chan = (FAR struct tiva_pwm_chan_s *)dev;
pwminfo("start PWM for channel %d\n", chan->channel_id);
/* Start the timer */
return tiva_pwm_timer(chan, info);
}
#endif
/****************************************************************************
* Name: tiva_pwm_timer
*
* Description:
* Configure PWM registers and start the PWM timer
*
* Input parameters:
* dev - A reference to the lower half PWM driver state structure
* info - A reference to the characteristics of the pulsed output
*
* Returned Value:
* Zero on success; a negated errno value on failure
*
****************************************************************************/
static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
FAR const struct pwm_info_s *info)
static inline int tiva_pwm_timer(FAR struct tiva_pwm_chan_s *chan,
FAR const struct pwm_info_s *info)
{
FAR struct tiva_pwm_chan_s *chan = (FAR struct tiva_pwm_chan_s *)dev;
pwminfo("start PWM for channel %d\n", chan->channel_id);
uint16_t duty = info->duty;
uint32_t frequency = info->frequency;
pwminfo("> frequency = %d\n", frequency);
pwminfo("> duty = %d\n", duty);
/* Configure PWM countdown mode (refer to TM4C1294NC 23.4.6) */
tiva_pwm_putreg(chan, TIVA_PWMn_CTL_OFFSET, 0);
if (chan->channel_id % 2 == 0)
{
tiva_pwm_putreg(chan, TIVA_PWMn_GENA_OFFSET,
GENx_LOW << TIVA_PWMn_GENx_ACTCMPAD | GENx_HIGH << TIVA_PWMn_GENx_ACTLOAD);
GENx_LOW << TIVA_PWMn_GENx_ACTCMPAD |
GENx_HIGH << TIVA_PWMn_GENx_ACTLOAD);
}
else
{
tiva_pwm_putreg(chan, TIVA_PWMn_GENB_OFFSET,
GENx_LOW << TIVA_PWMn_GENx_ACTCMPBD | GENx_HIGH << TIVA_PWMn_GENx_ACTLOAD);
GENx_LOW << TIVA_PWMn_GENx_ACTCMPBD |
GENx_HIGH << TIVA_PWMn_GENx_ACTLOAD);
}
/* Set the PWM period (refer to TM4C1294NC 23.4.7) */
@ -363,7 +609,7 @@ static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
uint32_t pwm_max_freq = g_pwm_freq;
uint32_t load = (uint32_t)(g_pwm_freq / frequency);
pwminfo("channel %d: load = %u (%08x)\n", chan->channel_id, load, load);
pwminfo("> load = %u (%08x)\n", load, load);
if (load >= g_pwm_counter || load < 1)
{
@ -383,7 +629,7 @@ static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
uint32_t comp = (uint32_t)((1 - (float)duty / g_pwm_counter) * load);
comp = (duty == 0) ? (comp - 1) : (comp);
pwminfo("channel %d: comp = %u (%08x)\n", chan->channel_id, comp, comp);
pwminfo("> comp = %u (%08x)\n", comp, comp);
if (chan->channel_id % 2 == 0)
{
@ -408,7 +654,7 @@ static int tiva_pwm_start(FAR struct pwm_lowerhalf_s *dev,
}
/****************************************************************************
* Name: pwm_stop
* Name: tiva_pwm_stop
*
* Description:
* Stop the pulsed output and reset the timer resources
@ -441,7 +687,7 @@ static int tiva_pwm_stop(FAR struct pwm_lowerhalf_s *dev)
}
/****************************************************************************
* Name: pwm_ioctl
* Name: tiva_pwm_ioctl
*
* Description:
* Lower-half logic may support platform-specific ioctl commands
@ -550,11 +796,12 @@ FAR struct pwm_lowerhalf_s *tiva_pwm_initialize(int channel)
return NULL;
}
pwminfo("channel %d: channel_id=%d, ", channel, chan->channel_id);
pwminfo("controller_id=%d, controller_base=%08x, ",
chan->controller_id, chan->controller_base);
pwminfo("generator_id=%d, generator_base=%08x\n",
chan->generator_id, chan->generator_base);
pwminfo("channel %d:\n", channel);
pwminfo("> channel_id = %d\n", chan->channel_id);
pwminfo("> controller_id = %d\n", chan->controller_id);
pwminfo("> controller_base = %08x\n", chan->controller_base);
pwminfo("> generator_id = %d\n", chan->generator_id);
pwminfo("> generator_base = %08x\n", chan->generator_base);
/* Enable PWM controller (refer to TM4C1294NC 23.4.1) */
@ -564,14 +811,55 @@ FAR struct pwm_lowerhalf_s *tiva_pwm_initialize(int channel)
/* Configure PWM Clock Configuration (refer to TM4C1294NC 23.4.5)
*
* On TM4C1294NC, configure the PWM clock source as 15MHz (the system
* clock 120MHz divided by 8)
* On TM4C1294NC, configure the PWM clock source as 1.875MHz (the system
* clock 120MHz divided by 64)
*
* TODO: need an algorithm to choose the best divider and load value combo.
*/
putreg32(CC_USEPWM << TIVA_PWM_CC_USEPWM | CC_PWMDIV_8 << TIVA_PWM_CC_PWMDIV,
putreg32(CC_USEPWM << TIVA_PWM_CC_USEPWM | CC_PWMDIV_64 << TIVA_PWM_CC_PWMDIV,
chan->controller_base + TIVA_PWM_CC);
#ifdef CONFIG_PWM_PULSECOUNT
/* Enable interrupt INTCMPAD mode */
tiva_pwm_putreg(chan, TIVA_PWMn_INTEN_OFFSET, INT_SET << INTCMPAD);
/* Attach IRQ handler and enable interrupt*/
switch (chan->channel_id)
{
#ifdef CONFIG_TIVA_PWM0_CHAN0
case 0:
irq_attach(chan->irq, tiva_pwm_gen0_interrupt);
up_enable_irq(chan->irq);
break;
#endif
#ifdef CONFIG_TIVA_PWM0_CHAN2
case 2:
irq_attach(chan->irq, tiva_pwm_gen1_interrupt);
up_enable_irq(chan->irq);
break;
#endif
#ifdef CONFIG_TIVA_PWM0_CHAN4
case 4:
irq_attach(chan->irq, tiva_pwm_gen2_interrupt);
up_enable_irq(chan->irq);
break;
#endif
#ifdef CONFIG_TIVA_PWM0_CHAN6
case 6:
irq_attach(chan->irq, tiva_pwm_gen3_interrupt);
up_enable_irq(chan->irq);
break;
#endif
}
#endif
return (FAR struct pwm_lowerhalf_s *)chan;
}

View File

@ -46,6 +46,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Must match definitions in up_testset.c */
#define SP_UNLOCKED false /* The Un-locked state */

View File

@ -62,7 +62,10 @@ pthread_mutex_init NXpthread_mutex_init
pthread_mutex_lock NXpthread_mutex_lock
pthread_mutex_unlock NXpthread_mutex_unlock
pthread_setspecific NXpthread_setspecific
pthread_setcancelstate NXpthread_setcancelstate
pthread_setcanceltype NXpthread_setcanceltype
pthread_sigmask NXpthread_sigmask
pthread_testcancel NXpthread_testcancel
pthread_yield NXpthread_yield
ptsname NXptsname
ptsname_r NXptsname_r

View File

@ -52,7 +52,7 @@
# include <arch/irq.h>
# ifdef CONFIG_SMP
# include <nuttx/sched.h>
# include <arch/spinlock.h>
# include <nuttx/spinlock.h>
# endif
#endif

View File

@ -22,6 +22,10 @@ config ARCH_CHIP_ESP32
of two CPUs is symmetric, meaning they use the same addresses to
access the same memory.
The two CPUs are named "PRO_CPU" and "APP_CPU" (for "protocol" and
"application"), however for most purposes the two CPUs are
interchangeable.
endchoice # XTENSA chip selection
config ARCH_FAMILY_LX6

View File

@ -378,7 +378,7 @@
#define ESP32_CPUINT_NEDGEPERIPHS 4
#define EPS32_CPUINT_EDGESET 0x50400400
#define ESP32_CPUINT_NNMIPERIPHS 4
#define ESP32_CPUINT_NNMIPERIPHS 1
#define EPS32_CPUINT_NMISET 0x00004000
#define ESP32_CPUINT_TIMER0 6
@ -388,11 +388,12 @@
#define ESP32_CPUINT_TIMER2 16
#define ESP32_CPUINT_SOFTWARE1 29
#define ESP32_CPUINT_NINTERNAL 5
#define ESP32_CPUINT_NINTERNAL 6
#define ESP32_CPUINT_MAX 31
#define EPS32_CPUINT_PERIPHSET 0xdffe6f3f
#define EPS32_CPUINT_INTERNALSET 0x200180c0
#define ESP32_NCPUINTS 32
#define ESP32_CPUINT_MAX (ESP32_NCPUINTS - 1)
#define EPS32_CPUINT_PERIPHSET 0xdffe773f
#define EPS32_CPUINT_INTERNALSET 0x200188c0
/* Priority 1: 0-10, 12-13, 17-18 (15)
* Priority 2: 19-21 (3)

View File

@ -108,20 +108,21 @@
# define REG_LBEG (_REG_LOOPS_START + 0)
# define REG_LEND (_REG_LOOPS_START + 1)
# define REG_LCOUNT (_REG_LOOPS_START + 2)
# define _REG_CALL0_START (_REG_LOOPS_START + 3)
# define _REG_WINDOW_TMPS (_REG_LOOPS_START + 3)
#else
# define _REG_CALL0_START _REG_LOOPS_START
# define _REG_WINDOW_TMPS _REG_LOOPS_START
#endif
#ifndef __XTENSA_CALL0_ABI__
/* Temporary space for saving stuff during window spill */
/* Temporary space for saving stuff during window spill.
* REVISIT: I don't think that we need so many temporaries.
*/
# define REG_TMP0 (_REG_CALL0_START + 0)
# define REG_TMP1 (_REG_CALL0_START + 1)
# define REG_TMP2 (_REG_CALL0_START + 2)
# define _REG_OVLY_START (_REG_CALL0_START + 3)
# define REG_TMP0 (_REG_WINDOW_TMPS + 0)
# define REG_TMP1 (_REG_WINDOW_TMPS + 1)
# define _REG_OVLY_START (_REG_WINDOW_TMPS + 2)
#else
# define _REG_OVLY_START _REG_CALL0_START
# define _REG_OVLY_START _REG_WINDOW_TMPS
#endif
#ifdef CONFIG_XTENSA_USE_OVLY

View File

@ -153,7 +153,8 @@ static inline uint32_t xtensa_get_cpenable(void)
__asm__ __volatile__
(
"rsr %0, CPENABLE" : "=r"(cpenable)
"\trsr %0, CPENABLE\n"
: "=r"(cpenable)
);
return cpenable;
@ -165,7 +166,9 @@ static inline void xtensa_set_cpenable(uint32_t cpenable)
{
__asm__ __volatile__
(
"wsr %0, PS" : : "r"(cpenable)
"\twsr %0, CPENABLE\n"
"\trsync\n"
: : "r"(cpenable)
);
}

View File

@ -104,10 +104,30 @@
/* Check if an interrupt stack size is configured */
#ifndef CONFIG_ARCH_INTERRUPTSTACK
# define CONFIG_ARCH_INTERRUPTSTACK 0
#define HAVE_INTERRUPTSTACK 1
#if !defined(CONFIG_ARCH_INTERRUPTSTACK)
# define CONFIG_ARCH_INTERRUPTSTACK 0
# undef HAVE_INTERRUPTSTACK
#elif CONFIG_ARCH_INTERRUPTSTACK < 16
# warning CONFIG_ARCH_INTERRUPTSTACK is to small
# undef HAVE_INTERRUPTSTACK
#endif
#define INTERRUPTSTACK_SIZE ((CONFIG_ARCH_INTERRUPTSTACK + 15) & ~15)
#define INTERRUPT_STACKWORDS (INTERRUPTSTACK_SIZE >> 2)
/* An IDLE thread stack size for CPU0 must be defined */
#if !defined(CONFIG_IDLETHREAD_STACKSIZE)
# error CONFIG_IDLETHREAD_STACKSIZE is not defined
#elif CONFIG_IDLETHREAD_STACKSIZE < 16
# error CONFIG_IDLETHREAD_STACKSIZE is to small
#endif
#define IDLETHREAD_STACKSIZE ((CONFIG_IDLETHREAD_STACKSIZE + 15) & ~15)
#define IDLETHREAD_STACKWORDS (IDLETHREAD_STACKSIZE >> 2)
/* Used for stack usage measurements */
#define STACK_COLOR 0xdeadbeef
@ -180,12 +200,16 @@ extern volatile uint32_t *g_current_regs[1];
#endif
/* Address of the saved user stack pointer */
#ifdef HAVE_INTERRUPTSTACK
/* The (optional) interrupt stack */
#if CONFIG_ARCH_INTERRUPTSTACK > 3
extern void g_intstackbase;
extern uint32_t g_intstack[INTERRUPT_STACKWORDS];
#endif
/* Address of the CPU0 IDLE thread */
extern uint32_t g_idlestack[IDLETHREAD_STACKWORDS];
/* These 'addresses' of these values are setup by the linker script. They are
* not actual uint32_t storage locations! They are only used meaningfully in the
* following way:
@ -266,7 +290,7 @@ void xtensa_coproc_disable(struct xtensa_cpstate_s *cpstate, int cpset);
/* IRQs */
uint32_t *xtensa_int_decode(uint32_t *regs);
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs);
uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs);
uint32_t xtensa_enable_cpuint(uint32_t *shadow, uint32_t intmask);
uint32_t xtensa_disable_cpuint(uint32_t *shadow, uint32_t intmask);
@ -293,7 +317,8 @@ void xtensa_coproc_restorestate(struct xtensa_cpstate_s *cpstate);
/* Signals */
void xtensa_sigdeliver(void);
void _xtensa_sig_trampoline(void);
void xtensa_sig_deliver(void);
/* Chip-specific functions **************************************************/
/* Chip specific functions defined in arch/xtensa/src/<chip> */

View File

@ -58,6 +58,27 @@
* CALL8, or CALL12 instructions to save 4, 8, or 12 live registers. Calls
* to routines that use a2..a7 for parameters may use only CALL8 or CALL12.
*
* Arguments are passed in both registers and memory. The first six incoming
* arguments are stored in registers a2 through a7, and additional arguments
* are stored on the stack starting at the current stack pointer a1. Because
* Xtensa uses register windows that rotate during a function call, outgoing
* arguments that will become the incoming arguments must be stored to
* different register numbers. Depending on the call instruction and, thus,
* the rotation of the register window, the arguments are passed starting
* starting with register a(2+N), where N is the size of the window rotation.
* Therefore, the first argument in case of a call4 instruction is placed into
* a6, and for a call8 instruction into a10. Large arguments (8-bytes) are
* always passed in an even/odd register pair even if that means to omit a
* register for alignment. The return values are stored in a2 through a7.
*
* return addr stack ptr arg0, arg1, arg2, arg3, arg4, arg5
* ----------- --------- ----------------------------------
* a0 a1 a2, a3, a4, a5, a6, a7
*
* call4 a4 a5 a6, a7, a8, a9, a10, a11
* call8 a8 a9 a10, a11, a12, a13, a14, a15
* call12 a12 a13 a14, a15 --- --- --- ---
*
* The stack pointer SP should only be modified by ENTRY and MOVSP
* instructions (except for initialization and restoration). If some other
* instruction modifies SP, any values in the register-spill area will not

View File

@ -0,0 +1,214 @@
/****************************************************************************
* arch/xtensa/src/common/xtensa_checkstack.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 <stdint.h>
#include <sched.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/tls.h>
#include <nuttx/board.h>
#include "xtensa.h"
#include "sched/sched.h"
#ifdef CONFIG_STACK_COLORATION
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static size_t do_stackcheck(uintptr_t alloc, size_t size);
/****************************************************************************
* Name: do_stackcheck
*
* Description:
* Determine (approximately) how much stack has been used be searching the
* stack memory for a high water mark. That is, the deepest level of the
* stack that clobbered some recognizable marker in the stack memory.
*
* Input Parameters:
* alloc - Allocation base address of the stack
* size - The size of the stack in bytes
*
* Returned value:
* The estimated amount of stack space used.
*
****************************************************************************/
static size_t do_stackcheck(uintptr_t alloc, size_t size)
{
FAR uintptr_t start;
FAR uintptr_t end;
FAR uint32_t *ptr;
size_t mark;
if (size == 0)
{
return 0;
}
/* Get aligned addresses of the top and bottom of the stack */
#ifdef CONFIG_TLS
/* Skip over the TLS data structure at the bottom of the stack */
DEBUGASSERT((alloc & TLS_STACK_MASK) == 0);
start = alloc + sizeof(struct tls_info_s);
#else
start = alloc & ~3;
#endif
end = (alloc + size + 3) & ~3;
/* Get the adjusted size based on the top and bottom of the stack */
size = end - start;
/* The Xtensa CPUs use a push-down stack: the stack grows toward lower
* addresses in memory. We need to start at the lowest address in the
* stack memory allocation and search to higher addresses. The first word
* we encounter that does not have the magic value is the high water mark.
*/
for (ptr = (FAR uint32_t *)start, mark = (size >> 2);
*ptr == STACK_COLOR && mark > 0;
ptr++, mark--);
/* If the stack is completely used, then this might mean that the stack
* overflowed from above (meaning that the stack is too small), or may
* have been overwritten from below meaning that some other stack or data
* structure overflowed.
*
* If you see returned values saying that the entire stack is being used
* then enable the following logic to see it there are unused areas in the
* middle of the stack.
*/
#if 0
if (mark + 16 > nwords)
{
int i;
int j;
ptr = (FAR uint32_t *)start;
for (i = 0; i < size; i += 4*64)
{
for (j = 0; j < 64; j++)
{
int ch;
if (*ptr++ == STACK_COLOR)
{
ch = '.';
}
else
{
ch = 'X';
}
up_putc(ch);
}
up_putc('\n');
}
}
#endif
/* Return our guess about how much stack space was used */
return mark << 2;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_check_stack and friends
*
* Description:
* Determine (approximately) how much stack has been used be searching the
* stack memory for a high water mark. That is, the deepest level of the
* stack that clobbered some recognizable marker in the stack memory.
*
* Input Parameters:
* None
*
* Returned value:
* The estimated amount of stack space used.
*
****************************************************************************/
size_t up_check_tcbstack(FAR struct tcb_s *tcb)
{
return do_stackcheck((uintptr_t)tcb->stack_alloc_ptr, tcb->adj_stack_size);
}
ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb)
{
return (ssize_t)tcb->adj_stack_size - (ssize_t)up_check_tcbstack(tcb);
}
size_t up_check_stack(void)
{
return up_check_tcbstack(this_task());
}
ssize_t up_check_stack_remain(void)
{
return up_check_tcbstack_remain(this_task());
}
#if CONFIG_ARCH_INTERRUPTSTACK > 3
size_t up_check_intstack(void)
{
return do_stackcheck((uintptr_t)&g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3));
}
size_t up_check_intstack_remain(void)
{
return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack();
}
#endif
#endif /* CONFIG_STACK_COLORATION */

View File

@ -116,7 +116,6 @@
_xtensa_context_save:
s32i a2, a2, (4 * REG_A2)
s32i a3, a2, (4 * REG_A3)
s32i a4, a2, (4 * REG_A4)
s32i a5, a2, (4 * REG_A5)
@ -146,22 +145,13 @@ _xtensa_context_save:
s32i a3, a2, (4 * REG_LCOUNT)
#endif
#ifndef __XTENSA_CALL0_ABI__
mov a9, a0 /* Preserve ret addr */
#endif
#ifndef __XTENSA_CALL0_ABI__
/* To spill the reg windows, temp. need pre-interrupt stack ptr and
* a4-15. Need to save a9,12,13 temporarily (in frame temps) and
* recover originals. Interrupts need to be disabled below
* XCHAL_EXCM_LEVEL and window overflow and underflow exceptions
* disabled (assured by PS.EXCM == 1).
* a4-15. Interrupts need to be disabled below XCHAL_EXCM_LEVEL and
* window overflow and underflow exceptions disabled (assured by
* PS.EXCM == 1).
*/
s32i a12, a2, (4 * REG_TMP0) /* Temp. save stuff in stack frame */
s32i a13, a2, (4 * REG_TMP1)
s32i a9, a2, (4 * REG_TMP2)
#ifdef CONFIG_XTENSA_USE_OVLY
/* Save the overlay state if we are supporting overlays. Since we just
* saved three registers, we can conveniently use them here. Note that
@ -171,17 +161,16 @@ _xtensa_context_save:
#error Overly support is not implemented
#endif
l32i a12, a2, (4 * REG_A12) /* Recover original a9,12,13 */
l32i a13, a2, (4 * REG_A13)
l32i a9, a2, (4 * REG_A9)
s32i a0, a2, (4 * REG_TMP0) /* Save return address */
s32i sp, a2, (4 * REG_TMP1) /* Save current stack pointer */
wsr a2, EXCSAVE_1 /* Preserve register save area */
#warning REVISIT: The following is probably not correct due to changes in registers
addi sp, sp, (4 * XCPTCONTEXT_SIZE) /* Restore the interruptee's SP */
call0 _xtensa_window_spill /* Preserves only a4,5,8,9,12,13 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE)
l32i a12, sp, (4 * REG_TMP0) /* Recover stuff from stack frame */
l32i a13, sp, (4 * REG_TMP1)
l32i a9, sp, (4 * REG_TMP2)
l32i sp, a2, (4 * REG_A1) /* Restore the interruptee's SP */
call0 _xtensa_window_spill /* Preserves only a4-a5, a8-a9, a12-a13 */
rsr a2, EXCSAVE_1 /* Save interruptee's a0 */
l32i a0, a2, (4 * REG_TMP0) /* Save return address */
l32i sp, a2, (4 * REG_TMP1) /* Save current stack pointer */
#endif
ret
@ -193,13 +182,11 @@ _xtensa_context_save:
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* This functions implements the moral equivalent of setjmp(). It is
* called from user code (with interrupts disabled) to save the current
* state of the running thread. This function always returns zero.
* However, it sets the saved value of the return address (A2) to 1.
* If the thread is restarted via _xtensa_contest_restore or
* If the thread is s via _xtensa_context_restore or
* xtensa_context_restore, it will appear as a second return from
* xtensa_context_save but with the returned value of 1 to distinguish
* the two cases.
@ -217,6 +204,24 @@ _xtensa_context_save:
* Assumptions:
* - Interrupts are disabled.
*
****************************************************************************/
#ifdef __XTENSA_CALL0_ABI__
/****************************************************************************
* Name: xtensa_context_save:
*
* Description:
* This implementation of xtensa_context_save for the case of the CALL0 ABI
*
* Input State:
* a0 = The return value to the caller.
* a2 = The address of the register state state structure
*
* Return state:
* a0 = The return value to the caller.
* a2, a12-a15 preserved as at entry
*
****************************************************************************/
.global xtensa_context_save
@ -227,30 +232,185 @@ _xtensa_context_save:
.align 4
xtensa_context_save:
ENTRY(16)
/* Set up for call to _xtensa_context_save() */
/* Set up for (potential) call to _xtensa_context_save() */
rsr a12, PS /* Save callee's PS */
s32i a12, a2, (4 * REG_PS)
s32i a3, a2, (4 * REG_A3) /* Get scratch register */
rsr a3, PS /* Save callee's PS */
s32i a3, a2, (4 * REG_PS)
s32i a0, a2, (4 * REG_PC) /* Save Return address as PC */
s32i a0, a2, (4 * REG_A0) /* Save callee's a0 */
s32i sp, a2, (4 * REG_A1) /* Save callee's SP */
movi a12, 1 /* Set saved A2 to 1 */
s32i a12, a2, (4 * REG_A2)
movi a3, 1 /* Set saved A2 to 1 */
s32i a3, a2, (4 * REG_A2)
/* Save the rest of the processor state */
/* Save the rest of the processor state. For the CALL0 ABI, we can user
* _xtensa_context_save(), Otherwise we duplicate the context save here
* to avoid the window spill.
*/
l32i r3, a2, (4 * REG_A3) /* Recover original a3 */
call0 _xtensa_context_save /* Save full register state */
/* Recover the return address and return zero */
l32i a0, a2, (4 * REG_A0) /* Recover return addess */
movi a2, 0 /* Return zero */
ret
RET(16)
.size xtensa_context_save, . - xtensa_context_save
#endif
/****************************************************************************
* This implementation of xtensa_context_save for the case of the window ABI.
* This case is more complex. For the Window ABI, there is a "hook" that
* performs the low level state state. xtensa_context_save() is a simply
* trampoline function that performs the window oeprations in that
* configuration.
****************************************************************************/
#ifndef __XTENSA_CALL0_ABI__
/****************************************************************************
* Name: _xtensa_save_hook:
*
* Input State:
* True return value has already been saved
* a0 = The return value into xtensa_context_save()
* a2 = The address of the register state state structure
*
* Return state:
* a0, a3 modified.
* Other values as on entry
* Returned value is in a3 (non-stanadard)
*
****************************************************************************/
.type _xtensa_save_hook, @function
.align 4
.literal_position
.align 4
_xtensa_save_hook:
/* Save the return value of 1 that will be used when returning from a
* context switch. NOTE that the returned value from this function is
* expected in a3 (not the usual a2). This also frees up a3 for a use
* as a scratch register.
*/
movi a3, 1 /* Set saved a3 to 1 */
s32i a3, a2, (4 * REG_A3)
/* Save the rest of the processor state.
*
* REVISIT: We could save a lot here. It should not be necessary to
* preserve all of these registers. The ABI permits volatile, callee-
* saved, registers to be clobbered on function calls. We save the
* whole tamale here mostly for debug purposes.
*
* NOTE that a3 was saved above. The true a0 return value was saved
* in xtensa_context_save. The a0 value saved below is the return into
* xtensa_context_save.
*/
rsr a3, PS /* Save callee's PS */
s32i a3, a2, (4 * REG_PS)
s32i a0, a2, (4 * REG_PC) /* Save Return address as PC */
s32i sp, a2, (4 * REG_A1) /* Save callee's SP */
s32i a2, a2, (4 * REG_A2)
s32i a4, a2, (4 * REG_A4) /* Save remaining registers */
s32i a5, a2, (4 * REG_A5)
s32i a6, a2, (4 * REG_A6)
s32i a7, a2, (4 * REG_A7)
s32i a8, a2, (4 * REG_A8)
s32i a9, a2, (4 * REG_A9)
s32i a10, a2, (4 * REG_A10)
s32i a11, a2, (4 * REG_A11)
/* Call0 ABI callee-saved regs a12-15 */
s32i a12, a2, (4 * REG_A12)
s32i a13, a2, (4 * REG_A13)
s32i a14, a2, (4 * REG_A14)
s32i a15, a2, (4 * REG_A15)
rsr a3, SAR
s32i a3, a2, (4 * REG_SAR)
#ifdef XCHAL_HAVE_LOOPS
rsr a3, LBEG
s32i a3, a2, (4 * REG_LBEG)
rsr a3, LEND
s32i a3, a2, (4 * REG_LEND)
rsr a3, LCOUNT
s32i a3, a2, (4 * REG_LCOUNT)
#endif
/* NOTE that the returned value is through a3 */
movi a3, 0 /* Return zero, no context switch */
ret
.size _xtensa_save_hook, . - _xtensa_save_hook
/****************************************************************************
* Name: xtensa_context_save:
*
* Description:
* This is the implementation of xtensa_context_save for the case of the
* window ABI. In the window ABI configuration, xtensa_context_save is a
* thin "trampoline" layer. It performs the ENTRY window operations on
* entry and the exit. A call0 is used to force the retun from the context
* switch to the window return within this trampoline.
*
* Input State:
* a0 = The true return value to the caller.
* a2 = The address of the register state state structure
*
* Return state:
* a0, a2, and a3 modified.
* Returned value is in a2
*
****************************************************************************/
.global xtensa_context_save
.type xtensa_context_save, @function
.align 4
.literal_position
.align 4
xtensa_context_save:
ENTRY(16)
/* Save the true return address in the register save structure (a0). */
s32i a0, a2, (4 * REG_A0) /* Save true return address (a0) */
/* Then perform the actual state save in _xtensa_save_hook. The saved
* EPC will be set to the return from this function then we will do the
* RET(16) window fix-up.
*/
call0 _xtensa_save_hook /* Save full register state */
/* a0 and a2 will be automatically restored in the context switch case
* with a3=1. In the non-context switch return with a2=0, a2 will still
* be valid, but we have to restore a0 ourself. The following should
* work in either case.
*/
l32i a0, a2, (4 * REG_A0) /* Recover the true return address (a0) */
mov a2, a3 /* Move a3 to the correct register for return */
RET(16)
.size xtensa_context_save, . - xtensa_context_save
#endif
/****************************************************************************
* Name: _xtensa_context_restore
@ -273,12 +433,13 @@ xtensa_context_save:
*
* Exit conditions:
* - A0 = Return address in caller.
* - Other registers are restored as detailed above (including A1 and A2).
* - Other registers are restored as detailed above
* - A2 is preserved
*
****************************************************************************/
.global _xtensa_context_restore
.type _xtensa_context_restore,@function
.type xtensa_context_restore,@function
.align 4
.literal_position
@ -287,12 +448,12 @@ xtensa_context_save:
_xtensa_context_restore:
#ifdef XCHAL_HAVE_LOOPS
l32i a2, a2, (4 * REG_LBEG)
l32i a3, a2, (4 * REG_LEND)
wsr a2, LBEG
l32i a2, a2, (4 * REG_LCOUNT)
wsr a3, LEND
wsr a2, LCOUNT
l32i a3, a2, (4 * REG_LBEG)
l32i a4, a2, (4 * REG_LEND)
wsr a3, LBEG
l32i a3, a2, (4 * REG_LCOUNT)
wsr a4, LEND
wsr a3, LCOUNT
#endif
#ifdef CONFIG_XTENSA_USE_OVLY
@ -326,10 +487,6 @@ _xtensa_context_restore:
l32i a14, a2, (4 * REG_A14)
l32i a15, a2, (4 * REG_A15)
/* Finally, restore A2 with the correct value */
l32i a2, a2, (4 * REG_A2)
ret
.size _xtensa_context_restore, . - _xtensa_context_restore
@ -339,8 +496,6 @@ _xtensa_context_restore:
*
* Description:
*
* NOTE: MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION!
*
* This functions implements the moral equivalent of longjmp(). It is
* called from user code (with interrupts disabled) to restor the current
* state of the running thread. This function always appears to be a
@ -372,8 +527,40 @@ _xtensa_context_restore:
.align 4
xtensa_context_restore:
ENTRY(16)
/* Restore the processor state */
#ifndef __XTENSA_CALL0_ABI__
/* Force a spill of the live registers of the thread that has been
* suspended.
*
* _xtensa_window_spill return state:
* a2, a3: clobbered
* a4,a5,a8,a9,a12,a13: preserved
* a6,a7,a10,a11,a14,a15 clobbered if they were part of window(s)
* to be spilled, otherwise they are the same as on entry
* loop registers: Perserved
* SAR: clobbered
*
* We need to preserve only a2 for _xtensa_context_restore
*/
mov a4, a2 /* Save a2 in a preserved register */
rsr a5, PS /* Save PS in preserved register */
movi a3, ~(PS_WOE_MASK | PS_INTLEVEL_MASK)
and a2, a5, a3 /* Clear WOE, INTLEVEL */
addi a2, a2, XCHAL_EXCM_LEVEL /* Set INTLEVEL = XCHAL_EXCM_LEVEL */
wsr a2, PS /* Apply to PS */
rsync
call0 _xtensa_window_spill
wsr a5, PS /* Restore PS */
rsync
mov a2, a4 /* Recover a2 */
#endif
/* Restore the processor state for the newly started thread */
call0 _xtensa_context_restore /* Restore full register state */
@ -382,10 +569,15 @@ xtensa_context_restore:
l32i a0, a2, (4 * REG_PS) /* Restore PS */
wsr a0, PS
l32i a0, a2, (4 * REG_PC) /* Set up for RFE */
rsr a0, EPC
wsr a0, EPC_1
l32i a0, a2, (4 * REG_A0) /* Restore a0 */
l32i a2, a2, (4 * REG_A2) /* Restore A2 */
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
*/
rfe /* And return from "exception" */
.size xtensa_context_restore, . - xtensa_context_restore

View File

@ -225,26 +225,12 @@ xtensa_coproc_savestate:
#ifdef __XTENSA_CALL0_ABI__
/* Need to preserve a8-11. _xtensa_coproc_savestate modifies a2-a7,
* a13-a15. So no registers need be saved.
* a13-a15. a12-a15 are callee saved registers so a13-a14 must be
* preserved.
*/
ENTRY(16)
/* Call _xtensa_coproc_savestate() with A2=address of co-processor
* save area.
*/
call0 _xtensa_coproc_savestate
RET(16)
#else
/* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7,
* a13-a15. So only a13-a15 need be preserved.
*/
ENTRY(16)
s32i a13, sp, LOCAL_OFFSET(1)
s32i a13, sp, LOCAL_OFFSET(1) /* Save clobbered registers */
s32i a14, sp, LOCAL_OFFSET(2)
s32i a15, sp, LOCAL_OFFSET(3)
@ -256,12 +242,30 @@ xtensa_coproc_savestate:
/* Restore a13-15 and return */
l32i a13, sp, LOCAL_OFFSET(1)
l32i a13, sp, LOCAL_OFFSET(1) /* Restore clobbered registers */
l32i a14, sp, LOCAL_OFFSET(2)
l32i a15, sp, LOCAL_OFFSET(3)
RET(16)
#else
/* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7,
* a13-a15. So a13-a15 may need to be preserved.
*/
ENTRY(32 /*16*/) /* REVISIT: Why 32? */
s32i a0, sp, LOCAL_OFFSET(1) /* Save return address */
/* Call _xtensa_coproc_savestate() with A2=address of co-processor
* save area.
*/
call0 _xtensa_coproc_savestate
/* Restore a0 and return */
l32i a0, sp, LOCAL_OFFSET(1) /* Recover return address */
RET(32 /*16*/) /* REVISIT: Why 32? */
#endif
.size xtensa_coproc_savestate, . - xtensa_coproc_savestate
@ -420,43 +424,47 @@ xtensa_coproc_restorestate:
#ifdef __XTENSA_CALL0_ABI__
/* Need to preserve a8-11. _xtensa_coproc_restorestate modifies a2-a7,
* a13-a15. So no registers need be saved.
* a13-a15. a12-a15 are callee saved registers so a13-a14 must be
* preserved.
*/
ENTRY(16)
/* Call _xtensa_coproc_restorestate() with A2=address of co-processor
* save area.
*/
call0 _xtensa_coproc_restorestate
RET(16)
#else
/* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7,
* a13-a15. So only a13-a15 need be preserved.
*/
ENTRY(16)
s32i a13, sp, LOCAL_OFFSET(1)
s32i a13, sp, LOCAL_OFFSET(1) /* Save clobbered values */
s32i a14, sp, LOCAL_OFFSET(2)
s32i a15, sp, LOCAL_OFFSET(3)
/* Call _xtensa_coproc_restorestate() with A2=address of co-processor
* save area.
* save area. Registers a0, a2-a7, a13-a15 have been trashed.
*/
call0 _xtensa_coproc_restorestate
/* Restore a13-15 and return */
/* Restore a13-a15 and return */
l32i a13, sp, LOCAL_OFFSET(1)
l32i a13, sp, LOCAL_OFFSET(1) /* Restore clobbered registers */
l32i a14, sp, LOCAL_OFFSET(2)
l32i a15, sp, LOCAL_OFFSET(3)
RET(16)
#else
/* Need to preserve a8-15. _xtensa_coproc_savestate modifies a2-a7,
* a13-a15. So a13-a15 may need to be preserved.
*/
ENTRY(32 /*16*/) /* REVISIT: Why 32? */
s32i a0, sp, LOCAL_OFFSET(1) /* Save return address */
/* Call _xtensa_coproc_restorestate() with A2=address of co-processor
* save area. Registers a0, a2-a7, a13-a15 have been trashed.
*/
call0 _xtensa_coproc_restorestate
/* Restore a0 and return */
l32i a0, sp, LOCAL_OFFSET(1) /* Recover return address */
RET(32 /*16*/) /* REVISIT: Why 32? */
#endif
.size xtensa_coproc_restorestate, . - xtensa_coproc_restorestate

View File

@ -40,6 +40,8 @@
#include <nuttx/config.h>
#include <arch/chip/core-isa.h>
#include "xtensa_abi.h"
#if XCHAL_HAVE_INTERRUPTS
/****************************************************************************
@ -69,6 +71,7 @@
.align 4
xtensa_enable_cpuint:
ENTRY(16)
movi a4, 0
xsr a4, INTENABLE /* Disables all interrupts */
@ -80,7 +83,7 @@ xtensa_enable_cpuint:
wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */
mov a3, a4 /* Return previous shadow content */
ret
RET(16)
.size xtensa_enable_cpuint, . - xtensa_enable_cpuint
@ -107,6 +110,7 @@ xtensa_enable_cpuint:
.align 4
xtensa_disable_cpuint:
ENTRY(16)
movi a4, 0
xsr a4, INTENABLE /* Disables all interrupts */
@ -119,7 +123,7 @@ xtensa_disable_cpuint:
wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */
mov a3, a4 /* Return previous shadow content */
ret
RET(16)
.size xtensa_disable_cpuint, . - xtensa_disable_cpuint

View File

@ -164,6 +164,7 @@ int up_cpu_paused(int cpu)
}
spin_unlock(&g_cpu_wait[cpu]);
return OK;
}
/****************************************************************************

View File

@ -78,6 +78,42 @@ static inline uint32_t xtensa_getsp(void)
return sp;
}
/****************************************************************************
* Name: up_taskdump
****************************************************************************/
#ifdef CONFIG_STACK_COLORATION
static void up_taskdump(FAR struct tcb_s *tcb, FAR void *arg)
{
/* Dump interesting properties of this task */
#if CONFIG_TASK_NAME_SIZE > 0
_alert("%s: PID=%d Stack Used=%lu of %lu\n",
tcb->name, tcb->pid, (unsigned long)up_check_tcbstack(tcb),
(unsigned long)tcb->adj_stack_size);
#else
_alert("PID: %d Stack Used=%lu of %lu\n",
tcb->pid, (unsigned long)up_check_tcbstack(tcb),
(unsigned long)tcb->adj_stack_size);
#endif
}
#endif
/****************************************************************************
* Name: up_showtasks
****************************************************************************/
#ifdef CONFIG_STACK_COLORATION
static inline void up_showtasks(void)
{
/* Dump interesting properties of each task in the crash environment */
sched_foreach(up_taskdump, NULL);
}
#else
# define up_showtasks()
#endif
/****************************************************************************
* Name: xtensa_stackdump
****************************************************************************/
@ -130,9 +166,8 @@ static inline void xtensa_registerdump(void)
(unsigned long)regs[REG_LCOUNT]);
#endif
#ifndef __XTENSA_CALL0_ABI__
_alert(" TMP0: %08lx TMP1: %08lx TMP2: %08lx\n",
(unsigned long)regs[REG_TMP0], (unsigned long)regs[REG_TMP1],
(unsigned long)regs[REG_TMP2]);
_alert(" TMP0: %08lx TMP1: %08lx\n",
(unsigned long)regs[REG_TMP0], (unsigned long)regs[REG_TMP1]);
#endif
}
}
@ -151,7 +186,7 @@ void xtensa_dumpstate(void)
uint32_t sp = xtensa_getsp();
uint32_t ustackbase;
uint32_t ustacksize;
#if CONFIG_ARCH_INTERRUPTSTACK > 3
#ifdef HAVE_INTERRUPTSTACK
uint32_t istackbase;
uint32_t istacksize;
#endif
@ -166,14 +201,8 @@ void xtensa_dumpstate(void)
if (rtcb->pid == 0)
{
#warning REVISIT: Need top of IDLE stack
#if 0
ustackbase = g_idle_topstack - 4;
ustacksize = CONFIG_IDLETHREAD_STACKSIZE;
#else
ustackbase = sp + 128;
ustacksize = 128;
#endif
ustackbase = (uint32_t)&g_idlestack[IDLETHREAD_STACKWORDS-1];
ustacksize = IDLETHREAD_STACKSIZE;
}
else
{
@ -184,9 +213,9 @@ void xtensa_dumpstate(void)
/* Get the limits on the interrupt stack memory */
#warning REVISIT interrupt stack
#if CONFIG_ARCH_INTERRUPTSTACK > 3
istackbase = (uint32_t)&g_intstackbase;
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4;
#ifdef HAVE_INTERRUPTSTACK
istackbase = (uint32_t)&g_intstack[INTERRUPT_STACKWORDS-1];
istacksize = INTERRUPTSTACK_SIZE;
/* Show interrupt stack info */
@ -194,6 +223,9 @@ void xtensa_dumpstate(void)
_alert("IRQ stack:\n");
_alert(" base: %08x\n", istackbase);
_alert(" size: %08x\n", istacksize);
#ifdef CONFIG_STACK_COLORATION
_alert(" used: %08x\n", up_check_intstack());
#endif
/* Does the current stack pointer lie within the interrupt
* stack?
@ -209,7 +241,7 @@ void xtensa_dumpstate(void)
* at the base of the interrupt stack.
*/
sp = g_intstackbase;
sp = &g_instack[INTERRUPTSTACK_SIZE - sizeof(uint32_t)];
_alert("sp: %08x\n", sp);
}
@ -218,10 +250,16 @@ void xtensa_dumpstate(void)
_alert("User stack:\n");
_alert(" base: %08x\n", ustackbase);
_alert(" size: %08x\n", ustacksize);
#ifdef CONFIG_STACK_COLORATION
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
#endif
#else
_alert("sp: %08x\n", sp);
_alert("stack base: %08x\n", ustackbase);
_alert("stack size: %08x\n", ustacksize);
#ifdef CONFIG_STACK_COLORATION
_alert("stack used: %08x\n", up_check_tcbstack(rtcb));
#endif
#endif
/* Dump the user stack if the stack pointer lies within the allocated user
@ -230,7 +268,7 @@ void xtensa_dumpstate(void)
if (sp > ustackbase || sp <= ustackbase - ustacksize)
{
#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4
#ifdef HAVE_INTERRUPTSTACK
_alert("ERROR: Stack pointer is not within allocated stack\n");
#endif
}
@ -242,6 +280,10 @@ void xtensa_dumpstate(void)
/* Then dump the registers (if available) */
xtensa_registerdump();
/* Dump the state of all tasks (if available) */
up_showtasks();
}
#endif /* CONFIG_ARCH_STACKDUMP */

View File

@ -63,6 +63,7 @@
#include <arch/chip/core-isa.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa.h"
#include "xtensa_abi.h"
#include "chip_macros.h"
#include "xtensa_timer.h"
@ -125,37 +126,25 @@
* a consequence of context switching.
*/
mov a12, sp /* a12 = address of save area */
._xtensa_dispatch_level&level&:
mov a12, sp /* Address of save area */
#ifdef __XTENSA_CALL0_ABI__
/* Get mask of pending, enabled interrupts at this level into a2. */
rsr a2, INTENABLE
rsr a3, INTERRUPT
movi a4, \mask
and a2, a2, a3
and a2, a2, a4
beqz a2, 5f /* Nothing to do */
/* If multiple bits are set then MSB has highest priority. */
extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
wsr a4, INTCLEAR /* Clear sw or edge-triggered interrupt */
beq a3, a4, 4f /* If timer interrupt then skip table */
and a2, a2, a4 /* a2 = Set of pending, enabled interrupts for this level */
beqz a2, 1f /* Nothing to do */
/* Call xtensa_int_decode with, passing that address of the register save
* area as a parameter (A2).
*/
mov a2, a12 /* Argument: Top of stack = register save area */
#ifdef __XTENSA_CALL0_ABI__
/* Argument 1: Set of CPU interrupt to dispatch */
mov a3, sp /* Argument 2: Top of stack = register save area */
call0 xtensa_int_decode /* Call xtensa_int_decode */
#else
call4 xtensa_int_decode /* Call xtensa_int_decode */
#endif
/* On return from xtensa_int_decode, a2 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
@ -163,55 +152,38 @@
* register save area. This may or may not reside on a stack.
*/
beq a2, a12, 3f /* If timer interrupt then skip table */
/* Switch stacks */
mov a12, a2 /* Switch to the save area of the new thread */
l32i a2, a12, (4 * REG_A1) /* Retrieve stack ptr and replace */
addi sp, a2, -(4 * XCPTCONTEXT_SIZE)
3:
j ._xtensa_dispatch_level&level& /* Check for more interrupts */
#else
/* Get mask of pending, enabled interrupts at this level into a2. */
4:
rsr a6, INTENABLE
rsr a2, INTERRUPT
movi a3, \mask
and a6, a6, a2
and a6, a6, a3 /* a6 = Set of pending, enabled interrupts for this level */
beqz a6, 1f /* Nothing to do */
.ifeq XT_TIMER_INTPRI - \level
/* Interrupt handler for the NuttX system timer if at this level.
* We'll be reading the interrupt state again after this call
* so no need to preserve any registers except a7 (pointer to
* state save area).
/* Call xtensa_int_decode with, passing that address of the register save
* area as a parameter (A2).
*/
movi a2, XTENSA_IRQ_TIMER&level& /* Argument 1: IRQ number */
mov a3, a12 /* Argument 2: Top of stack = register save area */
#ifdef __XTENSA_CALL0_ABI__
call0 xtensa_irq_dispatch /* Call xtensa_int_decode */
#else
call4 xtensa_irq_dispatch /* Call xtensa_int_decode */
/* Argument 1: Set of CPU interrupt to dispatch */
mov a7, sp /* Argument 2: Top of stack = register save area */
call4 xtensa_int_decode /* Call xtensa_int_decode */
/* On return from xtensa_int_decode, a6 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, a2 will instead refer to the TCB
* register save area. This may or may not reside on a stack.
*/
mov a12, a6 /* Switch to the save area of the new thread */
#endif
/* On return from xtensa_irq_dispatch, A2 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, A2 will instead refer to the TCB
* register save area.
*/
beq a2, a12, 5f /* If timer interrupt then skip table */
/* Switch stacks */
mov a12, a2 /* Switch to the save area of the new thread */
l32i a2, a12, (4 * REG_A1) /* Retrieve stack ptr and replace */
addi sp, a2, -(4 * XCPTCONTEXT_SIZE)
.endif
j ._xtensa_dispatch_level&level& /* Check for more interrupts */
5:
/* done */
/* Done */
1:
.endm
/****************************************************************************
@ -270,6 +242,7 @@
.section HANDLER_SECTION, "ax"
.type _xtensa_level1_handler, @function
.global _xtensa_level1_handler
.align 4
_xtensa_level1_handler:
@ -306,24 +279,25 @@ _xtensa_level1_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, PS
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_1
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
rsync /* Ensure EPS and EPC written */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure PS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_1 and jumps to
* the address in EPC_1.
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
*/
rfi 1
rfe /* And return from "exception" */
/****************************************************************************
* MEDIUM PRIORITY (LEVEL 2+) INTERRUPT LOW LEVEL HANDLERS.
@ -354,6 +328,7 @@ _xtensa_level1_handler:
#if XCHAL_EXCM_LEVEL >= 2
.section HANDLER_SECTION, "ax"
.type _xtensa_level2_handler, @function
.global _xtensa_level2_handler
.align 4
_xtensa_level2_handler:
@ -390,17 +365,17 @@ _xtensa_level2_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_2
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_2
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_2 and jumps to
@ -414,6 +389,7 @@ _xtensa_level2_handler:
#if XCHAL_EXCM_LEVEL >= 3
.section HANDLER_SECTION, "ax"
.type _xtensa_level3_handler, @function
.global _xtensa_level3_handler
.align 4
_xtensa_level3_handler:
@ -450,17 +426,17 @@ _xtensa_level3_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_3
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_3
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_3 and jumps to
@ -474,6 +450,7 @@ _xtensa_level3_handler:
#if XCHAL_EXCM_LEVEL >= 4
.section HANDLER_SECTION, "ax"
.type _xtensa_level4_handler, @function
.global _xtensa_level4_handler
.align 4
_xtensa_level4_handler:
@ -510,17 +487,17 @@ _xtensa_level4_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (presevers a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_4
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_4
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_4 and jumps to
@ -534,6 +511,7 @@ _xtensa_level4_handler:
#if XCHAL_EXCM_LEVEL >= 5
.section HANDLER_SECTION, "ax"
.type _xtensa_level5_handler, @function
.global _xtensa_level5_handler
.align 4
_xtensa_level5_handler:
@ -570,17 +548,17 @@ _xtensa_level5_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_5
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_5
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_5 and jumps to
@ -594,6 +572,7 @@ _xtensa_level5_handler:
#if XCHAL_EXCM_LEVEL >= 6
.section HANDLER_SECTION, "ax"
.type _xtensa_level6_handler, @function
.global _xtensa_level6_handler
.align 4
_xtensa_level6_handler:
@ -630,17 +609,17 @@ _xtensa_level6_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, EPS_6
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_6
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from interrupt. RFI restores the PS from EPS_6 and jumps to
@ -690,6 +669,7 @@ _xtensa_level6_handler:
#if XCHAL_INT_NLEVELS >=2 && XCHAL_EXCM_LEVEL < 2 && XCHAL_DEBUGLEVEL !=2
.section HANDLER_SECTION, "ax"
.type _xtensa_level2_handler, @function
.global _xtensa_level2_handler
.align 4
_xtensa_level2_handler:
@ -723,6 +703,7 @@ _xtensa_level2_handler:
#if XCHAL_INT_NLEVELS >=3 && XCHAL_EXCM_LEVEL < 3 && XCHAL_DEBUGLEVEL !=3
.section HANDLER_SECTION, "ax"
.type _xtensa_level3_handler, @function
.global _xtensa_level3_handler
.align 4
_xtensa_level3_handler:
@ -758,6 +739,7 @@ _xtensa_level3_handler:
#if XCHAL_INT_NLEVELS >=4 && XCHAL_EXCM_LEVEL < 4 && XCHAL_DEBUGLEVEL !=4
.section HANDLER_SECTION, "ax"
.type _xtensa_level4_handler, @function
.global _xtensa_level4_handler
.align 4
_xtensa_level4_handler:
@ -793,6 +775,7 @@ _xtensa_level4_handler:
#if XCHAL_INT_NLEVELS >=5 && XCHAL_EXCM_LEVEL < 5 && XCHAL_DEBUGLEVEL !=5
.section HANDLER_SECTION, "ax"
.type _xtensa_level5_handler, @function
.global _xtensa_level5_handler
.align 4
_xtensa_level5_handler:
@ -828,6 +811,7 @@ _xtensa_level5_handler:
#if XCHAL_INT_NLEVELS >=6 && XCHAL_EXCM_LEVEL < 6 && XCHAL_DEBUGLEVEL !=6
.section HANDLER_SECTION, "ax"
.type _xtensa_level6_handler, @function
.global _xtensa_level6_handler
.align 4
_xtensa_level6_handler:

View File

@ -99,14 +99,14 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs)
if (regs != CURRENT_REGS)
{
#if XCHAL_CP_NUM > 0
/* If an interrupt level context switch has occurred, then save the
* co-processor state in in the suspended thread's co-processor save
* area.
*
* NOTE 1. The state of the co-processor has not been altered and
* still represents the to-be-suspended thread.
* NOTE 2. We saved a reference TCB of the original thread on entry.
*/
/* If an interrupt level context switch has occurred, then save the
* co-processor state in in the suspended thread's co-processor save
* area.
*
* NOTE 1. The state of the co-processor has not been altered and
* still represents the to-be-suspended thread.
* NOTE 2. We saved a reference TCB of the original thread on entry.
*/
xtensa_coproc_savestate(&tcb->xcp.cpstate);

View File

@ -59,10 +59,13 @@
****************************************************************************/
#include <nuttx/config.h>
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "chip_macros.h"
/****************************************************************************
* Public Functions
****************************************************************************/
@ -95,6 +98,10 @@
.align 4
_xtensa_panic:
/* Save the exception code */
wsr a2, EXCSAVE_1
/* Save rest of interrupt context (A2=address of state save area on
* stack.
*/
@ -111,17 +118,25 @@ _xtensa_panic:
/* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
#ifdef __XTENSA_CALL0_ABI__
movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
#else
movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
#endif
wsr a0, PS
/* Call C panic handler: Arg1 (A2) = Exception code; Arg 2 (A3) = start
* of the register save area.
*/
mov a3, sp
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCSAVE_1
mov a3, sp
call0 xtensa_panic /* Call xtensa_panic. Should not return */
#else
rsr a6, EXCSAVE_1
mov a7, sp
call4 xtensa_panic /* Call xtensa_panic. Should not return */
#endif

View File

@ -150,7 +150,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* disabled
*/
CURRENT_REGS[REG_PC] = (uint32_t)xtensa_sigdeliver;
CURRENT_REGS[REG_PC] = (uint32_t)_xtensa_sig_trampoline;
#ifdef __XTENSA_CALL0_ABI__
CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
#else
@ -185,7 +185,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* disabled
*/
tcb->xcp.regs[REG_PC] = (uint32_t)xtensa_sigdeliver;
tcb->xcp.regs[REG_PC] = (uint32_t)_xtensa_sig_trampoline;
#ifdef __XTENSA_CALL0_ABI__
tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
#else

View File

@ -58,7 +58,7 @@
****************************************************************************/
/****************************************************************************
* Name: xtensa_sigdeliver
* Name: xtensa_sig_deliver
*
* Description:
* This is the a signal handling trampoline. When a signal action was
@ -67,7 +67,7 @@
*
****************************************************************************/
void xtensa_sigdeliver(void)
void xtensa_sig_deliver(void)
{
struct tcb_s *rtcb = this_task();
uint32_t regs[XCPTCONTEXT_REGS];

View File

@ -1,8 +1,10 @@
/****************************************************************************
* configs/compal_e88/boot.c
* arch/xtensa/src/common/xtensa_sigtramp.S
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Adapted from use in NuttX by:
*
* 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
@ -33,43 +35,49 @@
*
****************************************************************************/
.file "xtensa_sigtramp.S"
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/board.h>
#include "xtensa_abi.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_app_initialize
* Name: _xtensa_sig_trampoline
*
* Description:
* Perform architecture specific initialization
* Just sets up a proper window call to xtensa_sig_deliver(). We get
* here via a context switch setup in up_schedule_signaction. Which
* re-vectors the context switch to this location.
*
* Input Parameters:
* arg - The boardctl() argument is passed to the board_app_initialize()
* implementation without modification. The argument has no
* meaning to NuttX; the meaning of the argument is a contract
* between the board-specific initalization logic and the the
* matching application logic. The value cold be such things as a
* mode enumeration value, a set of DIP switch switch settings, a
* pointer to configuration data read from a file or serial FLASH,
* or whatever you would like to do with it. Every implementation
* should accept zero/NULL as a default configuration.
* Here we just call xtensa_sig_deliver() using the proper ABI. NOTE
* that this function cannot return and depends on the fact that
* xtensa_sig_deliver() does not return.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
* any failure to indicate the nature of the failure.
*
****************************************************************************/
#ifdef CONFIG_LIB_BOARDCTL
int board_app_initialize(uintptr_t arg)
{
return 0;
}
#endif /* CONFIG_LIB_BOARDCTL */
.text
.global _xtensa_sig_trampoline
.type _xtensa_sig_trampoline, @function
.align 4
_xtensa_sig_trampoline:
ENTRY(16) /* REVISIT: This should not be here */
#ifdef __XTENSA_CALL0_ABI__
cali0 xtensa_sig_deliver /* Call xtensa_sig_deliver */
#else
call4 xtensa_sig_deliver /* Call xtensa_sig_deliver */
#endif
1: j 1b /* xtensa_sig_deliver does not return */
.size _xtensa_sig_trampoline, . - _xtensa_sig_trampoline

View File

@ -59,10 +59,13 @@
****************************************************************************/
#include <nuttx/config.h>
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "chip_macros.h"
/****************************************************************************
* Assembly Language Macros
****************************************************************************/
@ -158,6 +161,7 @@ _xtensa_to_coproc_handler:
****************************************************************************/
.type _xtensa_user_handler, @function
.global _xtensa_user_handler
.align 4
_xtensa_user_handler:
@ -225,12 +229,13 @@ _xtensa_user_handler:
* beginning of the register save area.
*/
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a3, sp /* Argument 2 (a2) = pointer to register save area */
#ifdef __XTENSA_CALL0_ABI__
calx0 xtensa_user /* Call xtensa_user */
#else
rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a7, sp /* Argument 2 (a2) = pointer to register save area */
call4 xtensa_user /* Call xtensa_user */
#endif
@ -254,6 +259,7 @@ _xtensa_user_handler:
.section HANDLER_SECTION, "ax"
.type _xtensa_syscall_handler, @function
.align 4
_xtensa_syscall_handler:
/* Allocate stack frame and save A0, A1, and PS */
@ -323,54 +329,52 @@ _xtensa_syscall_handler:
ps_setup 1 a0
/* Dispatch the sycall as with other interrupts. */
/* At this point, sp holds the pointer to the register save area. That,
* however, may change as a consequence of context switching.
*/
mov a12, sp /* a12 = address of register save area */
movi a2, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov a3, a12 /* Argument 2: Top of stack = register save area */
#ifdef __XTENSA_CALL0_ABI__
call0 xtensa_irq_dispatch /* Call xtensa_int_decode */
#else
call4 xtensa_irq_dispatch /* Call xtensa_int_decode */
#endif
/* On return from xtensa_irq_dispatch, A2 will contain the address of the new
#ifdef __XTENSA_CALL0_ABI__
movi a2, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov a3, sp /* Argument 2: Top of stack = register save area */
call0 xtensa_irq_dispatch /* Call xtensa_int_decode */
/* On return from xtensa_irq_dispatch, a2 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, A2 will instead refer to the TCB
* register save area.
*/
beq a2, a12, 2f /* If timer interrupt then skip table */
#else
movi a6, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
mov a7, sp /* Argument 2: Top of stack = register save area */
call4 xtensa_irq_dispatch /* Call xtensa_int_decode */
/* Switch stacks */
/* On return from xtensa_irq_dispatch, a5 will contain the address of the new
* register save area. Usually this would be the same as the current SP.
* But in the event of a context switch, A2 will instead refer to the TCB
* register save area.
*/
mov a12, a2 /* Switch to the save area of the new thread */
l32i a2, a12, (4 * REG_A1) /* Retrieve stack ptr and replace */
addi sp, a2, -(4 * XCPTCONTEXT_SIZE)
2:
mov a2, a6 /* Switch to the new register save area */
#endif
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore
call0 _xtensa_context_restore /* (Preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
l32i a0, sp, (4 * REG_PS) /* Retrieve interruptee's PS */
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
wsr a0, PS
l32i a0, sp, (4 * REG_PC) /* Retrieve interruptee's PC */
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
wsr a0, EPC_1
l32i a0, sp, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i a2, sp, (4 * REG_A2) /* Retrieve interruptee's A2 */
l32i sp, sp, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
rsync /* Ensure EPS and EPC written */
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0 and then jumps
* to the address in EPC[1].
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
*/
rfe
@ -463,12 +467,13 @@ _xtensa_coproc_handler:
* beginning of the register save area.
*/
#ifdef __XTENSA_CALL0_ABI__
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a3, sp /* Argument 2 (a2) = pointer to register save area */
#ifdef __XTENSA_CALL0_ABI__
calx0 xtensa_user /* Call xtensa_user */
#else
rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
mov a7, sp /* Argument 2 (a2) = pointer to register save area */
call4 xtensa_user /* Call xtensa_user */
#endif

View File

@ -42,6 +42,7 @@
#include <arch/chip/core-isa.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa.h"
#include "xtensa_abi.h"
/****************************************************************************
@ -74,7 +75,7 @@ _xtensa_level2_vector:
/* Never returns here - call0 is used as a jump */
.end literal_prefix
.end literal_prefix
.size _xtensa_level2_vector, . - _xtensa_level2_vector
#endif
@ -93,7 +94,7 @@ _xtensa_level3_vector:
/* Never returns here - call0 is used as a jump */
.end literal_prefix
.end literal_prefix
.size _xtensa_level3_vector, . - _xtensa_level3_vector
#endif
@ -112,7 +113,7 @@ _xtensa_level4_vector:
/* Never returns here - call0 is used as a jump */
.end literal_prefix
.end literal_prefix
.size _xtensa_level5_vector, . - _xtensa_level5_vector
#endif
@ -131,8 +132,8 @@ _xtensa_level5_vector:
/* Never returns here - call0 is used as a jump */
.size _xtensa_level5_vector, . - _xtensa_level5_vector
.end literal_prefix
.size _xtensa_level5_vector, . - _xtensa_level5_vector
.end literal_prefix
#endif
#if XCHAL_EXCM_LEVEL >= 6
@ -202,7 +203,7 @@ _xtensa_nmi_vector:
s32i a0, sp, (4 * REG_A0)
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_NMI_EXCEPTION /* Address of state save on stack */
movi a2, XTENSA_NMI_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
#else
@ -226,10 +227,10 @@ _xtensa_nmi_vector:
****************************************************************************/
#if XCHAL_HAVE_DEBUG
.begin literal_prefix .debug_exception_vector
.section .debug_exception_vector.text, "ax"
.global _debug_exception_vector
.align 4
.begin literal_prefix .debug_exception_vector
.section .debug_exception_vector.text, "ax"
.global _debug_exception_vector
.align 4
_debug_exception_vector:
@ -244,7 +245,7 @@ _debug_exception_vector:
s32i a0, sp, (4 * REG_A0)
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_DEBUG_EXCEPTION /* Address of state save on stack */
movi a2, XTENSA_DEBUG_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.end literal_prefix
@ -261,10 +262,10 @@ _debug_exception_vector:
****************************************************************************/
#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
.begin literal_prefix .double_exception_vector
.section .double_exception_vector.text, "ax"
.global _double_exception_vector
.align 4
.begin literal_prefix .double_exception_vector
.section .double_exception_vector.text, "ax"
.global _double_exception_vector
.align 4
_double_exception_vector:
@ -279,14 +280,19 @@ _double_exception_vector:
s32i a0, sp, (4 * REG_PS)
rsr a0, DEPC /* Save interruptee's PC */
s32i a0, sp, (4 * REG_PC)
rsr a0, EXCSAVE_1 /* Save interruptee's a0 -- REVISIT */
rsr a0, EXCSAVE /* Save interruptee's a0 -- REVISIT */
s32i a0, sp, (4 * REG_A0)
rsr a0, EXCCAUSE /* Save the EXCCAUSE register */
s32i a0, sp, (4 * REG_EXCCAUSE)
rsr a0, EXCVADDR /* Save the EXCVADDR register */
s32i a0, sp, (4 * REG_EXCVADDR)
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_DOUBLE_EXCEPTION /* Address of state save on stack */
movi a2, XTENSA_DOUBLE_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.end literal_prefix
.end literal_prefix
#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
@ -298,10 +304,10 @@ _double_exception_vector:
*
****************************************************************************/
.begin literal_prefix .kernel_exception_vector
.section .kernel_exception_vector.text, "ax"
.global _kernel_exception_vector
.align 4
.begin literal_prefix .kernel_exception_vector
.section .kernel_exception_vector.text, "ax"
.global _kernel_exception_vector
.align 4
_kernel_exception_vector:
@ -320,7 +326,7 @@ _kernel_exception_vector:
s32i a0, sp, (4 * REG_A0)
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_KERNEL_EXCEPTION /* Address of state save on stack */
movi a2, XTENSA_KERNEL_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
.end literal_prefix
@ -333,15 +339,15 @@ _kernel_exception_vector:
*
****************************************************************************/
.begin literal_prefix .user_exception_vector
.section .user_exception_vector.text, "ax"
.global _user_exception_vector
.type _user_exception_vector, @function
.align 4
.begin literal_prefix .user_exception_vector
.section .user_exception_vector.text, "ax"
.global _user_exception_vector
.type _user_exception_vector, @function
.align 4
_user_exception_vector:
wsr a0, EXCSAVE_1 /* Preserve a0 */
call0 xtensa_user_handler /* And jump to user exception handler */
call0 _xtensa_user_handler /* And jump to user exception handler */
.end literal_prefix

View File

@ -35,14 +35,14 @@
# The start-up, "head", file. May be either a .S or a .c file.
HEAD_ASRC =
HEAD_CSRC = esp32_start.c
HEAD_ASRC = xtensa_vectors.S xtensa_window_vector.S xtensa_windowspill.S
HEAD_ASRC += xtensa_int_handlers.S xtensa_user_handler.S
HEAD_CSRC = esp32_start.c
# Common XTENSA files (arch/xtensa/src/common)
CMN_ASRCS = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S
CMN_ASRCS += xtensa_int_handlers.S xtensa_panic.S xtensa_user_handler.S
CMN_ASRCS += xtensa_vectors.S xtensa_windowspill.S
CMN_ASRCS = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S xtensa_panic.S
CMN_ASRCS += xtensa_sigtramp.S
CMN_CSRCS = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c
CMN_CSRCS += xtensa_cpenable.c xtensa_createstack.c xtensa_exit.c xtensa_idle.c
@ -68,6 +68,11 @@ ifeq ($(CONFIG_SMP),y)
CMN_CSRCS += xtensa_cpupause.c
endif
ifeq ($(CONFIG_STACK_COLORATION),y)
CMN_CSRCS += xtensa_checkstack.c
endif
# Use of common/xtensa_etherstub.c is deprecated. The preferred mechanism
# is to use CONFIG_NETDEV_LATEINIT=y to suppress the call to
# up_netinitialize() in xtensa_initialize.c. Then this stub would not be
@ -89,7 +94,7 @@ CHIP_CSRCS += esp32_timerisr.c
# Configuration-dependent ESP32 files
ifeq ($(CONFIG_SMP),y)
CHIP_ASRCS = esp32_cpuhead.S esp32_cpuindex.S
CHIP_ASRCS = esp32_cpuindex.S
CMN_CSRCS += esp32_cpuidlestack.c esp32_cpustart.c esp32_intercpu_interrupt.c
endif

View File

@ -1,148 +0,0 @@
/****************************************************************************
* arch/xtensa/src/esp32/esp32_cpuhead.S
*
* 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.
*
****************************************************************************/
.file "esp32_cpuhead.S"
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <arch/xtensa/xtensa_corebits.h>
#include <arch/esp32/core-isa.h>
#ifdef CONFIG_SMP
/****************************************************************************
* Private Data
****************************************************************************/
.section .noinit, "aw"
.global g_cpu1_idlestack
.type g_cpu1_idlestack, @object
.align 16
g_cpu1_idlestack:
.space (CONFIG_SMP_IDLETHREAD_STACKSIZE & ~15)
.Lcpu1_stacktop:
.size g_cpu1_idlestack, . - g_cpu1_idlestack
/****************************************************************************
* Public Functions
****************************************************************************/
.text
/****************************************************************************
* Name: __cpu[n]_start
*
* Description:
* Boot functions for each CPU (other than CPU0). These functions set up
* the ARM operating mode, the initial stack, and configure co-processor
* registers. At the end of the boot, esp32_cpu_boot() is called.
*
* These functions are provided by the common ARMv7-A logic.
*
* Input parameters:
* None
*
* Returned Value:
* Do not return.
*
****************************************************************************/
.global __cpu1_start
.type __cpu1_start, @function
.align 4
.Lcpu1_bottomofstack:
.long .Lcpu1_stacktop
.size .Lcpu1_bottomofstack, . - .Lcpu1_bottomofstack
#ifdef CONFIG_STACK_COLORATION
.Lcpu1_bottomofstack:
.long .Lcpu1_stacktop
.size .Lcpu1_bottomofstack, . - .Lcpu1_bottomofstack
.Lcpu1_stackcolor:
.long STACK_COLOR
.size .Lcpu1_stackcolor, . - .Lcpu1_stackcolor
#endif
.align 4
__cpu1_start:
/* Set up the stack pointer and the CPU index */
l32r sp, .Lcpu1_bottomofstack
/* REVIST: Does it make since to have co-processors enabled on the IDLE thread? */
#ifdef CONFIG_STACK_COLORATION
/* Write a known value to the IDLE thread stack to support stack
* monitoring logic
*/
mov a0, sp
l32r a1, .Lcpu1_bottomofstack
l32r a2, .Lcpu1_stackcolor
1:
s32i a2, a1, 0
addi a2, a2, 4
bne a1, a2, 1b
#endif
/* Set up the intiali PS */
#ifdef __XTENSA_CALL0_ABI__
movi a0, (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_EXCM)
#else
movi a0, (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1))
#endif
wsr a0, PS
/* Finish initialization in C */
movi a2, 1 /* Argument 1: CPU ID */
call0 xtensa_start_handler
/* xtensa_start_handler() does not return */
2: j 2b
.size __cpu1_start, . - __cpu1_start
#endif /* CONFIG_SMP */

View File

@ -36,6 +36,16 @@
#ifdef CONFIG_SMP
/****************************************************************************
* Public Data
****************************************************************************/
/* Address of the CPU0 IDLE thread */
uint32_t g_cpu1_idlestack[CPU1_IDLETHREAD_STACKWORDS]
__attribute__((aligned(16) section(".noinit")));
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -39,6 +39,7 @@
* Included Files
****************************************************************************/
#include "xtensa_abi.h"
#include "chip_macros.h"
/****************************************************************************
@ -71,6 +72,8 @@
.type up_cpu_index, @function
up_cpu_index:
ENTRY(16)
getcoreid a2
ret
RET(16)
.size up_cpu_index, . - up_cpu_index

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
@ -52,6 +53,8 @@
#include "esp32_cpuint.h"
#include "xtensa.h"
#include "sched/sched.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -147,6 +150,17 @@
#define ESP32_MAX_PRIORITY 5
#define ESP32_PRIO_INDEX(p) ((p) - ESP32_MIN_PRIORITY)
/****************************************************************************
* Public Data
****************************************************************************/
/* Maps a CPU interrupt to the IRQ of the attached peripheral interrupt */
uint8_t g_cpu0_intmap[ESP32_NCPUINTS];
#ifdef CONFIG_SMP
uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@ -156,18 +170,19 @@
*/
#ifdef CONFIG_SMP
static uint32_t g_intenable[CONFIG_SMP_NCPUS];
#else
static uint32_t g_intenable[1];
#endif
/* Bitsets for free, unallocated CPU interrupts */
/* Bitsets for free, unallocated CPU interrupts available to peripheral
* devices.
*/
static uint32_t g_free_cpuints = 0xffffffff;
static uint32_t g_cpu0_freeints = EPS32_CPUINT_PERIPHSET;
#ifdef CONFIG_SMP
static uint32_t g_cpu1_freeints = EPS32_CPUINT_PERIPHSET;
#endif
/* Bitsets for each interrupt priority 1-5 */
@ -184,11 +199,27 @@ static const uint32_t g_priority[5] =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: xtensa_disable_all
****************************************************************************/
static inline void xtensa_disable_all(void)
{
__asm__ __volatile__
(
"movi a2, 0\n"
"xsr a2, INTENABLE\n"
: : : "a2"
);
}
/****************************************************************************
* Name: esp32_alloc_cpuint
*
* Description:
* Allocate a CPU interrupt
* Allocate a CPU interrupt for a peripheral device. This function will
* not allocate any of the pre-allocated CPU interrupts for internal
* devices.
*
* Input Parameters:
* intmask - mask of candidate CPU interrupts. The CPU interrupt will be
@ -205,6 +236,7 @@ static const uint32_t g_priority[5] =
int esp32_alloc_cpuint(uint32_t intmask)
{
irqstate_t flags;
uint32_t *freeints;
uint32_t bitmask;
uint32_t intset;
int cpuint;
@ -216,7 +248,18 @@ int esp32_alloc_cpuint(uint32_t intmask)
flags = enter_critical_section();
intset = g_free_cpuints & intmask;
#ifdef CONFIG_SMP
if (this_cpu() != 0)
{
freeints = &g_cpu1_freeints;
}
else
#endif
{
freeints = &g_cpu0_freeints;
}
intset = *freeints & intmask;
if (intset != 0)
{
/* Skip over initial unavailable CPU interrupts quickly in groups
@ -224,7 +267,7 @@ int esp32_alloc_cpuint(uint32_t intmask)
*/
for (cpuint = 0, bitmask = 0xff;
cpuint <= ESP32_CPUINT_MAX;
cpuint <= ESP32_CPUINT_MAX && (intset & bitmask) == 0;
cpuint += 8, bitmask <<= 8);
/* Search for an unallocated CPU interrupt number in the remaining
@ -242,7 +285,7 @@ int esp32_alloc_cpuint(uint32_t intmask)
{
/* Got it! */
g_free_cpuints &= ~bitmask;
*freeints &= ~bitmask;
ret = cpuint;
break;
}
@ -257,6 +300,94 @@ int esp32_alloc_cpuint(uint32_t intmask)
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32_cpuint_initialize
*
* Description:
* Initialize CPU interrupts
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned on
* any failre.
*
****************************************************************************/
int esp32_cpuint_initialize(void)
{
uintptr_t regaddr;
uint8_t *intmap;
#ifdef CONFIG_SMP
int cpu;
#endif
int i;
#ifdef CONFIG_SMP
/* Which CPU are we initializing */
cpu = up_cpu_index();
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS);
#endif
/* Disable all CPU interrupts on this CPU */
xtensa_disable_all();
/* Detach all peripheral sources PRO CPU interrupts */
for (i = 0; i < ESP32_NPERIPHERALS; i++)
{
#ifdef CONFIG_SMP
if (cpu != 0)
{
regaddr = DPORT_APP_MAP_REGADDR(i);
}
else
#endif
{
regaddr = DPORT_PRO_MAP_REGADDR(i);
}
putreg32(NO_CPUINT, regaddr);
}
/* Initialize CPU interrupt-to-IRQ mapping table */
#ifdef CONFIG_SMP
if (cpu != 0)
{
intmap = g_cpu1_intmap;
}
else
#endif
{
intmap = g_cpu0_intmap;
}
/* Indiate that no peripheral interrupts are assigned to CPU interrupts */
memset(intmap, CPUINT_UNASSIGNED, ESP32_NCPUINTS);
/* Special case the 6 internal interrupts.
*
* CPU interrupt bit IRQ number
* --------------------------- ---------------------
* ESP32_CPUINT_TIMER0 6 XTENSA_IRQ_TIMER0 0
* SP32_CPUINT_SOFTWARE0 7 Not yet defined
* ESP32_CPUINT_PROFILING 11 Not yet defined
* ESP32_CPUINT_TIMER1 15 XTENSA_IRQ_TIMER1 1
* ESP32_CPUINT_TIMER2 16 XTENSA_IRQ_TIMER2 2
* ESP32_CPUINT_SOFTWARE1 29 Not yet defined
*/
intmap[ESP32_CPUINT_TIMER0] = XTENSA_IRQ_TIMER0;
intmap[ESP32_CPUINT_TIMER1] = XTENSA_IRQ_TIMER1;
intmap[ESP32_CPUINT_TIMER2] = XTENSA_IRQ_TIMER2;
return OK;
}
/****************************************************************************
* Name: up_disable_irq
*
@ -327,7 +458,7 @@ int esp32_alloc_levelint(int priority)
uint32_t intmask;
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY &&
priority <= ESP32_MAX_PRIORITY)
priority <= ESP32_MAX_PRIORITY);
/* Check if there are any level CPU interrupts available at the requested
* interrupt priority.
@ -359,7 +490,7 @@ int esp32_alloc_edgeint(int priority)
uint32_t intmask;
DEBUGASSERT(priority >= ESP32_MIN_PRIORITY &&
priority <= ESP32_MAX_PRIORITY)
priority <= ESP32_MAX_PRIORITY);
/* Check if there are any edge CPU interrupts available at the requested
* interrupt priority.
@ -386,6 +517,7 @@ int esp32_alloc_edgeint(int priority)
void esp32_free_cpuint(int cpuint)
{
irqstate_t flags;
uint32_t *freeints;
uint32_t bitmask;
DEBUGASSERT(cpuint >= 0 && cpuint < ESP32_CPUINT_NEDGEPERIPHS);
@ -394,8 +526,20 @@ void esp32_free_cpuint(int cpuint)
bitmask = (1ul << cpuint);
flags = enter_critical_section();
DEBUGASSERT((g_free_cpuints & bitmask) == 0);
g_free_cpuints |= bitmask;
#ifdef CONFIG_SMP
if (this_cpu() != 0)
{
freeints = &g_cpu1_freeints;
}
else
#endif
{
freeints = &g_cpu0_freeints;
}
DEBUGASSERT((*freeints & bitmask) == 0);
*freeints |= bitmask;
leave_critical_section(flags);
}
@ -407,8 +551,10 @@ void esp32_free_cpuint(int cpuint)
*
* Input Parameters:
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from ira.h to be assigned.
* periphid - The peripheral number from ira.h to be assigned to
* a CPU interrupt.
* cpuint - The CPU interrupt to receive the peripheral interrupt
* assignment.
*
* Returned Value:
* None
@ -418,6 +564,7 @@ void esp32_free_cpuint(int cpuint)
void esp32_attach_peripheral(int cpu, int periphid, int cpuint)
{
uintptr_t regaddr;
uint8_t *intmap;
DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS);
DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX);
@ -427,13 +574,18 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint)
if (cpu != 0)
{
regaddr = DPORT_APP_MAP_REGADDR(periphid);
intmap = g_cpu1_intmap;
}
else
#endif
{
regaddr = DPORT_PRO_MAP_REGADDR(periphid);
intmap = g_cpu0_intmap;
}
DEBUGASSERT(intmap[cpuint] == CPUINT_UNASSIGNED);
intmap[cpuint] = periphid + XTENSA_IRQ_FIRSTPERIPH;
putreg32(cpuint, regaddr);
}
@ -444,17 +596,21 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint)
* Detach a peripheral interupt from a CPU interrupt.
*
* Input Parameters:
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from ira.h to be assigned.
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from irq.h to be detached from the
* CPU interrupt.
* cpuint - The CPU interrupt from which the peripheral interrupt will
* be detached.
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_detach_peripheral(int cpu, int periphid)
void esp32_detach_peripheral(int cpu, int periphid, int cpuint)
{
uintptr_t regaddr;
uint8_t *intmap;
DEBUGASSERT(periphid >= 0 && periphid < ESP32_NPERIPHERALS);
#ifdef CONFIG_SMP
@ -463,12 +619,17 @@ void esp32_detach_peripheral(int cpu, int periphid)
if (cpu != 0)
{
regaddr = DPORT_APP_MAP_REGADDR(periphid);
intmap = g_cpu1_intmap;
}
else
#endif
{
regaddr = DPORT_PRO_MAP_REGADDR(periphid);
intmap = g_cpu0_intmap;
}
DEBUGASSERT(intmap[cpuint] != CPUINT_UNASSIGNED);
intmap[cpuint] = CPUINT_UNASSIGNED;
putreg32(NO_CPUINT, regaddr);
}

View File

@ -42,10 +42,46 @@
#include <nuttx/config.h>
#include <arch/irq.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define CPUINT_UNASSIGNED 0xff /* No peripheral assigned to this CPU interrupt */
/****************************************************************************
* Public Data
****************************************************************************/
/* Maps a CPU interrupt to the IRQ of the attached peripheral interrupt */
extern uint8_t g_cpu0_intmap[ESP32_NCPUINTS];
#ifdef CONFIG_SMP
extern uint8_t g_cpu1_intmap[ESP32_NCPUINTS];
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: esp32_cpuint_initialize
*
* Description:
* Initialize CPU interrupts
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned on
* any failre.
*
****************************************************************************/
int esp32_cpuint_initialize(void);
/****************************************************************************
* Name: esp32_alloc_levelint
*
@ -108,8 +144,10 @@ void esp32_free_cpuint(int cpuint);
*
* Input Parameters:
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from ira.h to be attached.
* periphid - The peripheral number from ira.h to be assigned to
* a CPU interrupt.
* cpuint - The CPU interrupt to receive the peripheral interrupt
* assignment.
*
* Returned Value:
* None
@ -125,14 +163,17 @@ void esp32_attach_peripheral(int cpu, int periphid, int cpuint);
* Detach a peripheral interupt from a CPU interrupt.
*
* Input Parameters:
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from ira.h to be detached.
* cpu - The CPU to receive the interrupt 0=PRO CPU 1=APP CPU
* periphid - The peripheral number from irq.h to be detached from the
* CPU interrupt.
* cpuint - The CPU interrupt from which the peripheral interrupt will
* be detached.
*
* Returned Value:
* None
*
****************************************************************************/
void esp32_detach_peripheral(int cpu, int periphid);
void esp32_detach_peripheral(int cpu, int periphid, int cpuint);
#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_CPUINT_H */

View File

@ -41,32 +41,38 @@
#include <stdint.h>
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/semaphore.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
#include "xtensa.h"
#include "chip/esp32_dport.h"
#include "chip/esp32_rtccntl.h"
#include "esp32_region.h"
#include "esp32_cpuint.h"
#include "esp32_smp.h"
#ifdef CONFIG_SMP
#warning REVISIT Need ets_set_appcpu_boot_addr() prototype
void ets_set_appcpu_boot_addr(uint32_t);
/****************************************************************************
* Private Data
****************************************************************************/
static volatile bool g_appcpu_started;
static sem_t g_appcpu_interlock;
static volatile spinlock_t g_appcpu_interlock SP_SECTION;
/****************************************************************************
* ROM function prototypes
****************************************************************************/
void Cache_Flush(int cpu);
void Cache_Read_Enable(int cpu);
void ets_set_appcpu_boot_addr(uint32_t start);
/****************************************************************************
* Private Functions
@ -88,20 +94,6 @@ static inline void xtensa_registerdump(FAR struct tcb_s *tcb)
# define xtensa_registerdump(tcb)
#endif
/****************************************************************************
* Name: xtensa_disable_all
****************************************************************************/
static inline void xtensa_disable_all(void)
{
__asm__ __volatile__
(
"movi a2, 0\n"
"xsr a2, INTENABLE\n"
: : : "a2"
);
}
/****************************************************************************
* Name: xtensa_attach_fromcpu0_interrupt
****************************************************************************/
@ -136,25 +128,52 @@ static inline void xtensa_attach_fromcpu0_interrupt(void)
****************************************************************************/
/****************************************************************************
* Name: xtensa_start_handler
* Name: xtensa_appcpu_start
*
* Description:
* This is the handler for SGI1. This handler simply returns from the
* interrupt, restoring the state of the new task at the head of the ready
* to run list.
* This is the entry point used with the APP CPU was started via
* up_cpu_start(). The actually start-up logic in in ROM and we boot up
* in C code.
*
* Input Parameters:
* Standard interrupt handling
* None
*
* Returned Value:
* Zero on success; a negated errno value on failure.
* None, does not return
*
****************************************************************************/
int xtensa_start_handler(int irq, FAR void *context)
void xtensa_appcpu_start(void)
{
FAR struct tcb_s *tcb = this_task();
int i;
register uint32_t sp;
#ifdef CONFIG_STACK_COLORATION
{
register uint32_t *ptr;
register int i;
/* If stack debug is enabled, then fill the stack with a recognizable value
* that we can use later to test for high water marks.
*/
for (i = 0, ptr = (uint32_t *)tcb->stack_alloc_ptr;
i < tcb->adj_stack_size;
i += sizeof(uint32_t))
{
*ptr++ = STACK_COLOR;
}
}
#endif
/* Move to the stack assigned to us by up_smp_start immediately. Although
* we were give a stack pointer at start-up, we don't know where that stack
* pointer is positioned respect to our memory map. The only safe option
* is to switch to a well-known IDLE thread stack.
*/
sp = (uint32_t)tcb->adj_stack_ptr;
__asm__ __volatile__("mov sp, %0\n" : : "r"(sp));
sinfo("CPU%d Started\n", up_cpu_index());
@ -167,7 +186,7 @@ int xtensa_start_handler(int irq, FAR void *context)
/* Handle interlock*/
g_appcpu_started = true;
sem_post(&g_appcpu_interlock);
spin_unlock(&g_appcpu_interlock);
/* Reset scheduler parameters */
@ -181,9 +200,9 @@ int xtensa_start_handler(int irq, FAR void *context)
esp32_region_protection();
/* Disable all PRO CPU interrupts */
/* Initialize CPU interrupts */
xtensa_disable_all();
(void)esp32_cpuint_initialize();
/* Attach and emable internal interrupts */
@ -193,13 +212,6 @@ int xtensa_start_handler(int irq, FAR void *context)
xtensa_attach_fromcpu0_interrupt();
#endif
/* Detach all peripheral sources APP CPU interrupts */
for (i = 0; i < ESP32_NPERIPHERALS; i++)
{
esp32_detach_peripheral(1, i);;
}
#if 0 /* Does it make since to have co-processors enabled on the IDLE thread? */
#if XTENSA_CP_ALLSET != 0
/* Set initial co-processor state */
@ -224,7 +236,6 @@ int xtensa_start_handler(int irq, FAR void *context)
*/
xtensa_context_restore(tcb->xcp.regs);
return OK;
}
/****************************************************************************
@ -261,7 +272,6 @@ int up_cpu_start(int cpu)
if (!g_appcpu_started)
{
uint32_t regval;
int ret;
/* Start CPU1 */
@ -277,8 +287,24 @@ int up_cpu_start(int cpu)
* have priority inheritance enabled.
*/
sem_init(&g_appcpu_interlock, 0, 0);
sem_setprotocol(&g_appcpu_interlock, SEM_PRIO_NONE);
spin_initialize(&g_appcpu_interlock, SP_LOCKED);
/* Flush and enable I-cache for APP CPU */
Cache_Flush(cpu);
Cache_Read_Enable(cpu);
/* Unstall the APP CPU */
regval = getreg32(RTC_CNTL_SW_CPU_STALL_REG);
regval &= ~RTC_CNTL_SW_STALL_APPCPU_C1_M;
putreg32(regval, RTC_CNTL_SW_CPU_STALL_REG);
regval = getreg32(RTC_CNTL_OPTIONS0_REG);
regval &= ~RTC_CNTL_SW_STALL_APPCPU_C0_M;
putreg32(regval, RTC_CNTL_OPTIONS0_REG);
/* Enable clock gating for the APP CPU */
regval = getreg32(DPORT_APPCPU_CTRL_B_REG);
regval |= DPORT_APPCPU_CLKGATE_EN;
@ -288,6 +314,8 @@ int up_cpu_start(int cpu)
regval &= ~DPORT_APPCPU_RUNSTALL;
putreg32(regval, DPORT_APPCPU_CTRL_C_REG);
/* Reset the APP CPU */
regval = getreg32(DPORT_APPCPU_CTRL_A_REG);
regval |= DPORT_APPCPU_RESETTING;
putreg32(regval, DPORT_APPCPU_CTRL_A_REG);
@ -298,20 +326,12 @@ int up_cpu_start(int cpu)
/* Set the CPU1 start address */
ets_set_appcpu_boot_addr((uint32_t)__cpu1_start);
ets_set_appcpu_boot_addr((uint32_t)xtensa_appcpu_start);
/* And way for the initial task to run on CPU1 */
/* And wait for the initial task to run on CPU1 */
while (!g_appcpu_started)
{
ret = sem_wait(&g_appcpu_interlock);
if (ret < 0)
{
DEBUGASSERT(errno == EINTR);
}
}
sem_destroy(&g_appcpu_interlock);
spin_lock(&g_appcpu_interlock);
DEBUGASSERT(g_appcpu_started);
}
return OK;

View File

@ -39,29 +39,32 @@
#include <nuttx/config.h>
#include <nuttx/sched.h>
#include <arch/chip/irq.h>
#include <stdint.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <arch/irq.h>
#include "chip/esp32_dport.h"
#include "xtensa.h"
#include "esp32_cpuint.h"
/****************************************************************************
* Private Data
* Private Functions
****************************************************************************/
static const uint8_t g_baseirq[3] =
{
ESP32_IRQ_SREG0,
ESP32_IRQ_SREG1,
ESP32_IRQ_SREG2
};
/****************************************************************************
* Name: xtensa_intclear
****************************************************************************/
static const uint8_t g_nirqs[3] =
static inline void xtensa_intclear(uint32_t mask)
{
ESP32_NIRQS_SREG0,
ESP32_NIRQS_SREG1,
ESP32_NIRQS_SREG2
};
__asm__ __volatile__
(
"movi a2, 0\n"
"wsr %0, INTCLEAR\n"
: "=r"(mask) : :
);
}
/****************************************************************************
* Public Functions
@ -75,80 +78,74 @@ static const uint8_t g_nirqs[3] =
* handling to the registered interrupt handler via xtensa_irq_dispatch().
*
* Input Parameters:
* regs - Saves processor state on the stack
* cpuints - Set of pending interrupts valid for this level
* regs - Saves processor state on the stack
*
* Returned Value:
* Normally the same vale as regs is returned. But, in the event of an
* Normally the same value as regs is returned. But, in the event of an
* interrupt level context switch, the returned value will, instead point
* to the saved processor state in the TCB of the newly started task.
*
****************************************************************************/
uint32_t *xtensa_int_decode(uint32_t *regs)
uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs)
{
uintptr_t regaddr;
uint32_t regval;
uint8_t *intmap;
uint32_t mask;
int regndx;
int bit;
int baseirq;
int nirqs;
#ifdef CONFIG_SMP
int cpu;
#endif
/* Select PRO or APP interrupt status registers */
#ifdef CONFIG_SMP
/* Select PRO or APP CPU interrupt mapping table */
cpu = up_cpu_index();
if (cpu == 0)
if (cpu != 0)
{
regaddr = DPORT_PRO_INTR_STATUS_0_REG;
intmap = g_cpu1_intmap;
}
else
#endif
{
regaddr = DPORT_APP_INTR_STATUS_0_REG;
intmap = g_cpu0_intmap;
}
/* Process each pending interrupt in each of the three interrupt status
* registers.
*/
/* Skip over zero bits, eight at a time */
for (regndx = 0; regndx < 3; regndx++)
for (bit = 0, mask = 0xff;
bit < ESP32_NCPUINTS && (cpuints & mask) == 0;
bit += 8, mask <<= 8);
/* Process each pending CPU interrupt */
for (; bit < ESP32_NCPUINTS && cpuints != 0; bit++)
{
/* Fetch the next register status register */
regval = getreg32(regaddr);
regaddr += sizeof(uint32_t);
/* Set up the search */
baseirq = g_baseirq[regndx];
nirqs = g_nirqs[regndx];
/* Decode and dispatch each pending bit in the interrupt status
* register.
*/
for (bit = 0; regval != 0 && bit < nirqs; bit++)
mask = (1 << bit);
if ((cpuints & mask) != 0)
{
/* Check if this interrupt is pending */
/* Extract the IRQ number from the mapping table */
mask = (1 << bit);
if ((regval & mask) != 0)
{
/* Yes.. Dispatch the interrupt. Note that regs may be
* altered in the case of an interrupt level context switch.
*/
uint8_t irq = intmap[bit];
DEBUGASSERT(irq != CPUINT_UNASSIGNED);
regs = xtensa_irq_dispatch(baseirq + bit, regs);
/* Clear software or edge-triggered interrupt */
/* Clear this bit in the sampled status register so that
* perhaps we can exit this loop sooner.
*/
xtensa_intclear(mask);
regval &= ~mask;
}
/* Dispatch the CPU interrupt.
*
* NOTE that regs may be altered in the case of an interrupt
* level context switch.
*/
regs = xtensa_irq_dispatch((int)irq, regs);
/* Clear the bit in the pending interrupt so that perhaps
* we can exit the look early.
*/
cpuints &= ~mask;
}
}

View File

@ -41,7 +41,6 @@
#include <sys/types.h>
#include <stdint.h>
#include <sched.h>
#include <assert.h>
#include <errno.h>
@ -86,7 +85,7 @@ static int esp32_fromcpu_interrupt(int fromcpu)
int intcode;
int tocpu;
DEBUGASSERT(regs != NULL);
DEBUGASSERT((unsigned)fromcpu < CONFIG_SMP_NCPUS);
/* Clear the interrupt from the other CPU */
@ -155,14 +154,8 @@ int xtensa_intercpu_interrupt(int tocpu, int intcode)
{
int fromcpu;
DEBUGASSERT((unsigned)cpu < CONFIG_SMP_NCPUS &&
(unsigned)incode <= UINT8_MAX);
/* Disable context switching so that some other thread does not attempt to
* take the spinlock on the same CPU.
*/
sched_lock();
DEBUGASSERT((unsigned)tocpu < CONFIG_SMP_NCPUS &&
(unsigned)intcode <= UINT8_MAX);
/* Make sure that each inter-cpu event is atomic. The spinlock should
* only be locked if we just completed sending an interrupt to this
@ -195,7 +188,6 @@ int xtensa_intercpu_interrupt(int tocpu, int intcode)
putreg32(DPORT_CPU_INTR_FROM_CPU_1, DPORT_CPU_INTR_FROM_CPU_1_REG);
}
sched_unlock();
return OK;
}

View File

@ -98,20 +98,6 @@ static void esp32_irq_dump(const char *msg, int irq)
# define esp32_irq_dump(msg, irq)
#endif
/****************************************************************************
* Name: xtensa_disable_all
****************************************************************************/
static inline void xtensa_disable_all(void)
{
__asm__ __volatile__
(
"movi a2, 0\n"
"xsr a2, INTENABLE\n"
: : : "a2"
);
}
/****************************************************************************
* Name: xtensa_attach_fromcpu1_interrupt
****************************************************************************/
@ -151,20 +137,11 @@ static inline void xtensa_attach_fromcpu1_interrupt(void)
void xtensa_irq_initialize(void)
{
int i;
/* Initialize CPU interrupts */
/* Disable all PRO CPU interrupts */
(void)esp32_cpuint_initialize();
xtensa_disable_all();
/* Detach all peripheral sources PRO CPU interrupts */
for (i = 0; i < ESP32_NPERIPHERALS; i++)
{
esp32_detach_peripheral(0, i);
}
#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3
#if defined(CONFIG_STACK_COLORATION) && defined(HAVE_INTERRUPTSTACK)
/* Colorize the interrupt stack for debug purposes */
#warning Missing logic
@ -187,7 +164,7 @@ void xtensa_irq_initialize(void)
#endif
#ifndef CONFIG_SUPPRESS_INTERRUPTS
/* And finally, enable interrupts */
/* And finally, enable interrupts. Also clears PS.EXCM */
up_irq_enable();
#endif

View File

@ -146,7 +146,7 @@
struct esp32_config_s
{
const uint32_t uartbase; /* Base address of UART registers */
const uint32_t uartbase; /* Base address of UART registers */
xcpt_t handler; /* Interrupt handler */
uint8_t periph; /* UART peripheral ID */
uint8_t irq; /* IRQ number assigned to the peripheral */
@ -455,8 +455,8 @@ static void esp32_disableallints(struct esp32_dev_s *priv, uint32_t *intena)
static int esp32_setup(struct uart_dev_s *dev)
{
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
#ifndef CONFIG_SUPPRESS_UART_CONFIG
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
uint32_t clkdiv;
uint32_t regval;
uint32_t conf0;
@ -586,6 +586,19 @@ static int esp32_setup(struct uart_dev_s *dev)
static void esp32_shutdown(struct uart_dev_s *dev)
{
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
uint32_t status;
/* Wait for outgoing FIFO to clear. The ROM bootloader does not flush
* the FIFO before handing over to user code, so some of this output is
* not currently seen when the UART is reconfigured in early stages of
* startup.
*/
do
{
status = esp32_serialin(priv, UART_STATUS_OFFSET);
}
while ((status & UART_TXFIFO_CNT_M) != 0);
/* Disable all UART interrupts */
@ -642,7 +655,9 @@ static int esp32_attach(struct uart_dev_s *dev)
priv->cpuint = esp32_alloc_levelint(1);
if (priv->cpuint < 0)
{
ret = priv->cpuint;
/* Failed to allocate a CPU interrupt of this type */
return priv->cpuint;
}
/* Set up to receive peripheral interrupts on the current CPU */
@ -701,7 +716,7 @@ static void esp32_detach(struct uart_dev_s *dev)
cpu = 0;
#endif
esp32_detach_peripheral(cpu, priv->config->periph);
esp32_detach_peripheral(cpu, priv->config->periph, priv->cpuint);
/* And release the CPU interrupt */
@ -725,6 +740,8 @@ static int esp32_interrupt(struct uart_dev_s *dev)
struct esp32_dev_s *priv;
uint32_t regval;
uint32_t status;
uint32_t enabled;
unsigned int nfifo;
int passes;
bool handled;
@ -741,28 +758,48 @@ static int esp32_interrupt(struct uart_dev_s *dev)
handled = false;
priv->status = esp32_serialin(priv, UART_INT_RAW_OFFSET);
status = esp32_serialin(priv, UART_STATUS_OFFSET);
enabled = esp32_serialin(priv, UART_INT_ENA_OFFSET);
/* Clear pending interrupts */
regval = (UART_RXFIFO_FULL_INT_CLR_S | UART_FRM_ERR_INT_CLR_S |
UART_RXFIFO_TOUT_INT_CLR_S | UART_TX_DONE_INT_CLR_S |
UART_TXFIFO_EMPTY_INT_CLR_S);
regval = (UART_RXFIFO_FULL_INT_CLR | UART_FRM_ERR_INT_CLR |
UART_RXFIFO_TOUT_INT_CLR | UART_TX_DONE_INT_CLR |
UART_TXFIFO_EMPTY_INT_CLR);
esp32_serialout(priv, UART_INT_CLR_OFFSET, regval);
if ((status & UART_RXFIFO_CNT_M) > 0)
/* Are Rx interrupts enabled? The upper layer may hold off Rx input
* by disabling the Rx interrupts if there is no place to saved the
* data, possibly resulting in an overrun error.
*/
if ((enabled & (UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA)) != 0)
{
/* Is there any data waiting in the Rx FIFO? */
nfifo = (status & UART_RXFIFO_CNT_M) >> UART_RXFIFO_CNT_S;
if (nfifo > 0)
{
/* Received data in the RXFIFO! ... Process incoming bytes */
uart_recvchars(dev);
handled = true;
}
}
/* Are Tx interrupts enabled? The upper layer will disable Tx interrupts
* when it has nothing to send.
*/
if ((enabled & (UART_TX_DONE_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA)) != 0)
{
/* Received data in the RXFIFO ... process incoming bytes */
nfifo = (status & UART_TXFIFO_CNT_M) >> UART_TXFIFO_CNT_S;
if (nfifo < 0x7f)
{
/* The TXFIFO is not full ... process outgoing bytes */
uart_recvchars(dev);
handled = true;
}
if ((status & UART_TXFIFO_CNT_M) < 0x7f)
{
/* The TXFIFO is not full ... process outgoing bytes */
uart_xmitchars(dev);
handled = true;
uart_xmitchars(dev);
handled = true;
}
}
}
@ -1032,8 +1069,11 @@ static int esp32_receive(struct uart_dev_s *dev, unsigned int *status)
static void esp32_rxint(struct uart_dev_s *dev, bool enable)
{
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
irqstate_t flags;
int regval;
flags = enter_critical_section();
if (enable)
{
/* Receive an interrupt when their is anything in the Rx data register (or an Rx
@ -1042,8 +1082,8 @@ static void esp32_rxint(struct uart_dev_s *dev, bool enable)
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
regval = esp32_serialin(priv, UART_INT_ENA_OFFSET);
regval |= (UART_RXFIFO_FULL_INT_CLR_S | UART_FRM_ERR_INT_CLR_S |
UART_RXFIFO_TOUT_INT_CLR_S);
regval |= (UART_RXFIFO_FULL_INT_ENA | UART_FRM_ERR_INT_ENA |
UART_RXFIFO_TOUT_INT_ENA);
esp32_serialout(priv, UART_INT_ENA_OFFSET, regval);
#endif
}
@ -1051,10 +1091,13 @@ static void esp32_rxint(struct uart_dev_s *dev, bool enable)
{
/* Disable the RX interrupts */
esp32_serialout(priv, UART_INT_CLR_OFFSET,
(UART_RXFIFO_FULL_INT_CLR_S | UART_FRM_ERR_INT_CLR_S |
UART_RXFIFO_TOUT_INT_CLR_S));
regval = esp32_serialin(priv, UART_INT_ENA_OFFSET);
regval &= ~(UART_RXFIFO_FULL_INT_ENA | UART_FRM_ERR_INT_ENA |
UART_RXFIFO_TOUT_INT_ENA);
esp32_serialout(priv, UART_INT_ENA_OFFSET, regval);
}
leave_critical_section(flags);
}
/****************************************************************************
@ -1099,20 +1142,19 @@ static void esp32_txint(struct uart_dev_s *dev, bool enable)
{
struct esp32_dev_s *priv = (struct esp32_dev_s *)dev->priv;
irqstate_t flags;
int regval;
flags = enter_critical_section();
if (enable)
{
uint32_t regval;
/* Set to receive an interrupt when the TX holding register register
* is empty
*/
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
regval = esp32_serialin(priv, UART_INT_ENA_OFFSET);
regval |= (UART_TX_DONE_INT_ENA_S | UART_TXFIFO_EMPTY_INT_ENA_S);
regval |= (UART_TX_DONE_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA);
esp32_serialout(priv, UART_INT_ENA_OFFSET, regval);
/* Fake a TX interrupt here by just calling uart_xmitchars() with
@ -1126,8 +1168,9 @@ static void esp32_txint(struct uart_dev_s *dev, bool enable)
{
/* Disable the TX interrupt */
esp32_serialout(priv, UART_INT_CLR_OFFSET,
(UART_TX_DONE_INT_CLR_S | UART_TXFIFO_EMPTY_INT_CLR_S));
regval = esp32_serialin(priv, UART_INT_ENA_OFFSET);
regval &= ~(UART_TX_DONE_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA);
esp32_serialout(priv, UART_INT_ENA_OFFSET, regval);
}
leave_critical_section(flags);
@ -1253,7 +1296,7 @@ int up_putc(int ch)
/* Add CR */
while(!esp32_txready(&CONSOLE_DEV));
esp32_send(&CONSOLE_DEV, 'r');
esp32_send(&CONSOLE_DEV, '\r');
}
while(!esp32_txready(&CONSOLE_DEV));

View File

@ -44,6 +44,20 @@
#ifdef CONFIG_SMP
/****************************************************************************
* Pre-procesor Definitions
****************************************************************************/
/* An IDLE thread stack size for CPU0 must be defined */
#if !defined(CONFIG_SMP_IDLETHREAD_STACKSIZE)
# error CONFIG_SMP_IDLETHREAD_STACKSIZE is not defined
#elif CONFIG_SMP_IDLETHREAD_STACKSIZE < 16
# error CONFIG_SMP_IDLETHREAD_STACKSIZE is to small
#endif
#define CPU1_IDLETHREAD_STACKSIZE ((CONFIG_SMP_IDLETHREAD_STACKSIZE + 15) & ~15)
#define CPU1_IDLETHREAD_STACKWORDS (CPU1_IDLETHREAD_STACKSIZE >> 2)
/****************************************************************************
* Public Data
@ -51,8 +65,7 @@
/* This is the CPU1 IDLE stack */
#define CPU1_IDLETHREAD_STACKSIZE (CONFIG_SMP_IDLETHREAD_STACKSIZE & ~15)
extern uint32_t g_cpu1_idlestack[CPU1_IDLETHREAD_STACKSIZE / 34];
extern uint32_t g_cpu1_idlestack[CPU1_IDLETHREAD_STACKWORDS];
/****************************************************************************
* Public Functions

View File

@ -33,14 +33,25 @@
#include <string.h>
#include <nuttx/init.h>
#include <nuttx/irq.h>
#include "xtensa.h"
#include "xtensa_attr.h"
#include "chip/esp32_dport.h"
#include "chip/esp32_rtccntl.h"
#include "esp32_clockconfig.h"
#include "esp32_region.h"
#include "esp32_start.h"
#include "xtensa.h"
/****************************************************************************
* Public Data
****************************************************************************/
/* Address of the CPU0 IDLE thread */
uint32_t g_idlestack[IDLETHREAD_STACKWORDS]
__attribute__((aligned(16) section(".noinit")));
/****************************************************************************
* Public Functions
@ -62,6 +73,7 @@
void IRAM_ATTR __start(void)
{
uint32_t regval;
uint32_t sp;
/* Kill the watchdog timer */
@ -73,6 +85,39 @@ void IRAM_ATTR __start(void)
regval &= ~(1 << 14);
putreg32(regval, 0x6001f048);
/* Make sure that normal interrupts are disabled. This is really only an
* issue when we are started in un-usual ways (such as from IRAM). In this
* case, we can at least defer some unexpected interrupts left over from the
* last program execution.
*/
up_irq_disable();
#ifdef CONFIG_STACK_COLORATION
{
register uint32_t *ptr;
register int i;
/* If stack debug is enabled, then fill the stack with a recognizable value
* that we can use later to test for high water marks.
*/
for (i = 0, ptr = g_idlestack; i < IDLETHREAD_STACKWORDS; i++)
{
*ptr++ = STACK_COLOR;
}
}
#endif
/* Move the stack to a known location. Although we were give a stack
* pointer at start-up, we don't know where that stack pointer is positioned
* respect to our memory map. The only safe option is to switch to a well-
* known IDLE thread stack.
*/
sp = (uint32_t)g_idlestack + IDLETHREAD_STACKSIZE;
__asm__ __volatile__("mov sp, %0\n" : : "r"(sp));
/* Make page 0 access raise an exception */
esp32_region_protection();
@ -108,4 +153,5 @@ void IRAM_ATTR __start(void)
/* Bring up NuttX */
os_start();
for(; ; ); /* Should not return */
}

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